compositor, drm: set per-surface Presentation feedback flags
authorPekka Paalanen <pekka.paalanen@collabora.co.uk>
Wed, 17 Dec 2014 14:20:41 +0000 (16:20 +0200)
committerBryce Harrington <bryce@osg.samsung.com>
Wed, 21 Jan 2015 01:13:20 +0000 (17:13 -0800)
PRESENTATION_FEEDBACK_KIND_ZERO_COPY is a flag that needs to be set for
each surface separately. Some surfaces may be zero-copy (as defined by
Presentation feedback) while some are not.

A complication with Weston is that a surface may have multiple views on
screen. All copies (views) of the surface are required to be zero-copy
for the ZERO_COPY flag to be set.

Backends set per-view feedback flags during the assing_planes hook, and
then Weston core collects the flags from all views of a surface.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Mario Kleiner <mario.kleiner.de@gmail.com>
Tested-by: Mario Kleiner <mario.kleiner.de@gmail.com>
src/compositor-drm.c
src/compositor.c
src/compositor.h

index 86adfee..209f2ae 100644 (file)
@@ -1130,11 +1130,24 @@ drm_assign_planes(struct weston_output *output_base)
                        next_plane = drm_output_prepare_overlay_view(output, ev);
                if (next_plane == NULL)
                        next_plane = primary;
+
                weston_view_move_to_plane(ev, next_plane);
+
                if (next_plane == primary)
                        pixman_region32_union(&overlap, &overlap,
                                              &ev->transform.boundingbox);
 
+               if (next_plane == primary ||
+                   next_plane == &output->cursor_plane) {
+                       /* cursor plane involves a copy */
+                       ev->psf_flags = 0;
+               } else {
+                       /* All other planes are a direct scanout of a
+                        * single client buffer.
+                        */
+                       ev->psf_flags = PRESENTATION_FEEDBACK_KIND_ZERO_COPY;
+               }
+
                pixman_region32_fini(&surface_overlap);
        }
        pixman_region32_fini(&overlap);
index 8085b05..c2c975d 100644 (file)
@@ -470,6 +470,9 @@ struct weston_presentation_feedback {
 
        /* XXX: could use just wl_resource_get_link() instead */
        struct wl_list link;
+
+       /* The per-surface feedback flags */
+       uint32_t psf_flags;
 };
 
 static void
@@ -515,7 +518,7 @@ weston_presentation_feedback_present(
                                             ts->tv_nsec,
                                             refresh_nsec,
                                             seq >> 32, seq & 0xffffffff,
-                                            flags);
+                                            flags | feedback->psf_flags);
        wl_resource_destroy(feedback->resource);
 }
 
@@ -2000,6 +2003,31 @@ weston_compositor_build_view_list(struct weston_compositor *compositor)
                        surface_free_unused_subsurface_views(view->surface);
 }
 
+static void
+weston_output_take_feedback_list(struct weston_output *output,
+                                struct weston_surface *surface)
+{
+       struct weston_view *view;
+       struct weston_presentation_feedback *feedback;
+       uint32_t flags = 0xffffffff;
+
+       if (wl_list_empty(&surface->feedback_list))
+               return;
+
+       /* All views must have the flag for the flag to survive. */
+       wl_list_for_each(view, &surface->views, surface_link) {
+               /* ignore views that are not on this output at all */
+               if (view->output_mask & (1u << output->id))
+                       flags &= view->psf_flags;
+       }
+
+       wl_list_for_each(feedback, &surface->feedback_list, link)
+               feedback->psf_flags = flags;
+
+       wl_list_insert_list(&output->feedback_list, &surface->feedback_list);
+       wl_list_init(&surface->feedback_list);
+}
+
 static int
 weston_output_repaint(struct weston_output *output)
 {
@@ -2019,11 +2047,14 @@ weston_output_repaint(struct weston_output *output)
        /* Rebuild the surface list and update surface transforms up front. */
        weston_compositor_build_view_list(ec);
 
-       if (output->assign_planes && !output->disable_planes)
+       if (output->assign_planes && !output->disable_planes) {
                output->assign_planes(output);
-       else
-               wl_list_for_each(ev, &ec->view_list, link)
+       } else {
+               wl_list_for_each(ev, &ec->view_list, link) {
                        weston_view_move_to_plane(ev, &ec->primary_plane);
+                       ev->psf_flags = 0;
+               }
+       }
 
        wl_list_init(&frame_callback_list);
        wl_list_for_each(ev, &ec->view_list, link) {
@@ -2035,9 +2066,7 @@ weston_output_repaint(struct weston_output *output)
                                            &ev->surface->frame_callback_list);
                        wl_list_init(&ev->surface->frame_callback_list);
 
-                       wl_list_insert_list(&output->feedback_list,
-                                           &ev->surface->feedback_list);
-                       wl_list_init(&ev->surface->feedback_list);
+                       weston_output_take_feedback_list(output, ev->surface);
                }
        }
 
index 3a26635..aa87ec0 100644 (file)
@@ -815,6 +815,9 @@ struct weston_view {
         * displayed on.
         */
        uint32_t output_mask;
+
+       /* Per-surface Presentation feedback flags, controlled by backend. */
+       uint32_t psf_flags;
 };
 
 struct weston_surface_state {