compositor: finish frame if redraw fails
If we are about to finish a frame, but a redraw is pending and we let the compositor redraw, we need to check for errors. If the redraw fails and the backend cannot schedule a page-flip, we need to finish the frame, anyway. All backends except DRM use a timer to schedule frames. Hence, they cannot fail. But for DRM, we need to be able to handle drmModePageFlip() failures in case access got revoked. This fixes a bug where logind+drm caused keyboard input to be missed as we didn't reenable it after a failed page-flip during deactivation.
This commit is contained in:
committed by
Kristian Høgsberg
parent
3c688c5e33
commit
1edf44ce26
+14
-6
@@ -576,7 +576,7 @@ drm_output_set_gamma(struct weston_output *output_base,
|
|||||||
weston_log("set gamma failed: %m\n");
|
weston_log("set gamma failed: %m\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
drm_output_repaint(struct weston_output *output_base,
|
drm_output_repaint(struct weston_output *output_base,
|
||||||
pixman_region32_t *damage)
|
pixman_region32_t *damage)
|
||||||
{
|
{
|
||||||
@@ -588,12 +588,12 @@ drm_output_repaint(struct weston_output *output_base,
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (output->destroy_pending)
|
if (output->destroy_pending)
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
if (!output->next)
|
if (!output->next)
|
||||||
drm_output_render(output, damage);
|
drm_output_render(output, damage);
|
||||||
if (!output->next)
|
if (!output->next)
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
mode = container_of(output->base.current_mode, struct drm_mode, base);
|
mode = container_of(output->base.current_mode, struct drm_mode, base);
|
||||||
if (!output->current) {
|
if (!output->current) {
|
||||||
@@ -603,7 +603,7 @@ drm_output_repaint(struct weston_output *output_base,
|
|||||||
&mode->mode_info);
|
&mode->mode_info);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
weston_log("set mode failed: %m\n");
|
weston_log("set mode failed: %m\n");
|
||||||
return;
|
goto err_pageflip;
|
||||||
}
|
}
|
||||||
output_base->set_dpms(output_base, WESTON_DPMS_ON);
|
output_base->set_dpms(output_base, WESTON_DPMS_ON);
|
||||||
}
|
}
|
||||||
@@ -612,7 +612,7 @@ drm_output_repaint(struct weston_output *output_base,
|
|||||||
output->next->fb_id,
|
output->next->fb_id,
|
||||||
DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
|
DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
|
||||||
weston_log("queueing pageflip failed: %m\n");
|
weston_log("queueing pageflip failed: %m\n");
|
||||||
return;
|
goto err_pageflip;
|
||||||
}
|
}
|
||||||
|
|
||||||
output->page_flip_pending = 1;
|
output->page_flip_pending = 1;
|
||||||
@@ -664,7 +664,15 @@ drm_output_repaint(struct weston_output *output_base,
|
|||||||
output->vblank_pending = 1;
|
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
|
static void
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ fbdev_output_repaint_pixman(struct weston_output *base, pixman_region32_t *damag
|
|||||||
1000000 / output->mode.refresh);
|
1000000 / output->mode.refresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
fbdev_output_repaint(struct weston_output *base, pixman_region32_t *damage)
|
fbdev_output_repaint(struct weston_output *base, pixman_region32_t *damage)
|
||||||
{
|
{
|
||||||
struct fbdev_output *output = to_fbdev_output(base);
|
struct fbdev_output *output = to_fbdev_output(base);
|
||||||
@@ -214,6 +214,8 @@ fbdev_output_repaint(struct weston_output *base, pixman_region32_t *damage)
|
|||||||
wl_event_source_timer_update(output->finish_frame_timer,
|
wl_event_source_timer_update(output->finish_frame_timer,
|
||||||
1000000 / output->mode.refresh);
|
1000000 / output->mode.refresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ finish_frame_handler(void *data)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
headless_output_repaint(struct weston_output *output_base,
|
headless_output_repaint(struct weston_output *output_base,
|
||||||
pixman_region32_t *damage)
|
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);
|
wl_event_source_timer_update(output->finish_frame_timer, 16);
|
||||||
|
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ rdp_output_start_repaint_loop(struct weston_output *output)
|
|||||||
weston_output_finish_frame(output, msec);
|
weston_output_finish_frame(output, msec);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
rdp_output_repaint(struct weston_output *output_base, pixman_region32_t *damage)
|
rdp_output_repaint(struct weston_output *output_base, pixman_region32_t *damage)
|
||||||
{
|
{
|
||||||
struct rdp_output *output = container_of(output_base, struct rdp_output, base);
|
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);
|
&ec->primary_plane.damage, damage);
|
||||||
|
|
||||||
wl_event_source_timer_update(output->finish_frame_timer, 16);
|
wl_event_source_timer_update(output->finish_frame_timer, 16);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ rpi_output_start_repaint_loop(struct weston_output *output)
|
|||||||
weston_output_finish_frame(output, time);
|
weston_output_finish_frame(output, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
rpi_output_repaint(struct weston_output *base, pixman_region32_t *damage)
|
rpi_output_repaint(struct weston_output *base, pixman_region32_t *damage)
|
||||||
{
|
{
|
||||||
struct rpi_output *output = to_rpi_output(base);
|
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() */
|
/* schedule callback to rpi_output_update_complete() */
|
||||||
rpi_dispmanx_update_submit(update, output);
|
rpi_dispmanx_update_submit(update, output);
|
||||||
DBG("frame update submitted\n");
|
DBG("frame update submitted\n");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ wayland_output_start_repaint_loop(struct weston_output *output_base)
|
|||||||
wl_surface_commit(output->parent.surface);
|
wl_surface_commit(output->parent.surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
wayland_output_repaint(struct weston_output *output_base,
|
wayland_output_repaint(struct weston_output *output_base,
|
||||||
pixman_region32_t *damage)
|
pixman_region32_t *damage)
|
||||||
{
|
{
|
||||||
@@ -227,7 +227,7 @@ wayland_output_repaint(struct weston_output *output_base,
|
|||||||
|
|
||||||
pixman_region32_subtract(&ec->primary_plane.damage,
|
pixman_region32_subtract(&ec->primary_plane.damage,
|
||||||
&ec->primary_plane.damage, damage);
|
&ec->primary_plane.damage, damage);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ x11_output_start_repaint_loop(struct weston_output *output)
|
|||||||
weston_output_finish_frame(output, msec);
|
weston_output_finish_frame(output, msec);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
x11_output_repaint_gl(struct weston_output *output_base,
|
x11_output_repaint_gl(struct weston_output *output_base,
|
||||||
pixman_region32_t *damage)
|
pixman_region32_t *damage)
|
||||||
{
|
{
|
||||||
@@ -339,6 +339,7 @@ x11_output_repaint_gl(struct weston_output *output_base,
|
|||||||
&ec->primary_plane.damage, damage);
|
&ec->primary_plane.damage, damage);
|
||||||
|
|
||||||
wl_event_source_timer_update(output->finish_frame_timer, 10);
|
wl_event_source_timer_update(output->finish_frame_timer, 10);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -446,7 +447,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,
|
x11_output_repaint_shm(struct weston_output *output_base,
|
||||||
pixman_region32_t *damage)
|
pixman_region32_t *damage)
|
||||||
{
|
{
|
||||||
@@ -477,6 +478,7 @@ x11_output_repaint_shm(struct weston_output *output_base,
|
|||||||
}
|
}
|
||||||
|
|
||||||
wl_event_source_timer_update(output->finish_frame_timer, 10);
|
wl_event_source_timer_update(output->finish_frame_timer, 10);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|||||||
+8
-4
@@ -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)
|
weston_output_repaint(struct weston_output *output, uint32_t msecs)
|
||||||
{
|
{
|
||||||
struct weston_compositor *ec = output->compositor;
|
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 weston_frame_callback *cb, *cnext;
|
||||||
struct wl_list frame_callback_list;
|
struct wl_list frame_callback_list;
|
||||||
pixman_region32_t output_damage;
|
pixman_region32_t output_damage;
|
||||||
|
int r;
|
||||||
|
|
||||||
/* Rebuild the surface list and update surface transforms up front. */
|
/* Rebuild the surface list and update surface transforms up front. */
|
||||||
weston_compositor_build_surface_list(ec);
|
weston_compositor_build_surface_list(ec);
|
||||||
@@ -1404,7 +1405,7 @@ weston_output_repaint(struct weston_output *output, uint32_t msecs)
|
|||||||
if (output->dirty)
|
if (output->dirty)
|
||||||
weston_output_update_matrix(output);
|
weston_output_update_matrix(output);
|
||||||
|
|
||||||
output->repaint(output, &output_damage);
|
r = output->repaint(output, &output_damage);
|
||||||
|
|
||||||
pixman_region32_fini(&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_counter++;
|
||||||
animation->frame(animation, output, msecs);
|
animation->frame(animation, output, msecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -1440,14 +1443,15 @@ weston_output_finish_frame(struct weston_output *output, uint32_t msecs)
|
|||||||
struct weston_compositor *compositor = output->compositor;
|
struct weston_compositor *compositor = output->compositor;
|
||||||
struct wl_event_loop *loop =
|
struct wl_event_loop *loop =
|
||||||
wl_display_get_event_loop(compositor->wl_display);
|
wl_display_get_event_loop(compositor->wl_display);
|
||||||
int fd;
|
int fd, r;
|
||||||
|
|
||||||
output->frame_time = msecs;
|
output->frame_time = msecs;
|
||||||
|
|
||||||
if (output->repaint_needed &&
|
if (output->repaint_needed &&
|
||||||
compositor->state != WESTON_COMPOSITOR_SLEEPING &&
|
compositor->state != WESTON_COMPOSITOR_SLEEPING &&
|
||||||
compositor->state != WESTON_COMPOSITOR_OFFSCREEN) {
|
compositor->state != WESTON_COMPOSITOR_OFFSCREEN) {
|
||||||
weston_output_repaint(output, msecs);
|
r = weston_output_repaint(output, msecs);
|
||||||
|
if (!r)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -219,7 +219,7 @@ struct weston_output {
|
|||||||
struct wl_list mode_list;
|
struct wl_list mode_list;
|
||||||
|
|
||||||
void (*start_repaint_loop)(struct weston_output *output);
|
void (*start_repaint_loop)(struct weston_output *output);
|
||||||
void (*repaint)(struct weston_output *output,
|
int (*repaint)(struct weston_output *output,
|
||||||
pixman_region32_t *damage);
|
pixman_region32_t *damage);
|
||||||
void (*destroy)(struct weston_output *output);
|
void (*destroy)(struct weston_output *output);
|
||||||
void (*assign_planes)(struct weston_output *output);
|
void (*assign_planes)(struct weston_output *output);
|
||||||
|
|||||||
Reference in New Issue
Block a user