[PATCH 3/4] compositor: unify sprite and primary handling a bit

Kristian Høgsberg krh at bitplanet.net
Mon Jan 16 19:09:11 PST 2012


On Mon, Jan 16, 2012 at 5:40 PM, Jesse Barnes <jbarnes at virtuousgeek.org> wrote:
> In assign_planes, we try to assign the primary buffer to the primary
> plane, then look for additional surfaces to match to display planes.  At
> present time, we'll then flip all those buffers onto the screen in a
> synchronized way, then clean up and release the buffers when the
> corresponding page flip or vblank event arrives.
> ---
>  src/compositor-drm.c |  102 ++++++++++++++++++++++++++++++++++++++++++-------
>  src/compositor.c     |    2 +
>  src/compositor.h     |    1 +
>  3 files changed, 90 insertions(+), 15 deletions(-)
>
> diff --git a/src/compositor-drm.c b/src/compositor-drm.c
> index 4b42394..9e25ffd 100644
> --- a/src/compositor-drm.c
> +++ b/src/compositor-drm.c
> @@ -81,6 +81,8 @@ struct drm_output {
>
>        struct wl_list sprite_list;
>
> +       struct wl_list sprite_surfaces;
> +
>        uint32_t fs_surf_fb_id;
>        uint32_t pending_fs_surf_fb_id;
>  };
> @@ -169,10 +171,16 @@ drm_output_present(struct weston_output *output_base)
>        struct drm_output *output = (struct drm_output *) output_base;
>        struct drm_compositor *c =
>                (struct drm_compositor *) output->base.compositor;
> +       struct drm_sprite *s;
>        uint32_t fb_id = 0;
> +       uint32_t flags = 0;
> +       int ret, queued_sprite = 0;
>
>        glFlush();
>
> +       /*
> +        * First, flip the scanout surface onto the screen.
> +        */
>        output->current ^= 1;
>
>        if (output->pending_fs_surf_fb_id != 0) {
> @@ -185,10 +193,73 @@ drm_output_present(struct weston_output *output_base)
>                        fb_id,
>                        DRM_MODE_PAGE_FLIP_EVENT, output);
>
> +       /*
> +        * Now, update all the sprite surfaces
> +        */
> +       wl_list_for_each(s, &output->sprite_list, output_link) {
> +               if (s->fb_id != 0) {
> +                       ret = drmModeSetPlane(c->drm.fd, s->plane_id,
> +                                             output->crtc_id, s->fb_id, flags,
> +                                             s->dest_x, s->dest_y,
> +                                             s->dest_w, s->dest_h,
> +                                             s->src_x, s->src_y,
> +                                             s->src_w, s->src_h);
> +                       if (ret)
> +                               fprintf(stderr, "setplane failed: %d: %s\n",
> +                                       ret, strerror(errno));
> +                       queued_sprite = 1;
> +               }
> +       }
> +
> +       /*
> +        * Request a vblank event for the next seqno so we can free up
> +        * the sprite surfaces.
> +        */
> +       if (queued_sprite) {
> +               drmVBlank vbl = {
> +                       .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
> +                       .request.sequence = 1,
> +               };
> +
> +               vbl.request.signal = (unsigned long)output;
> +               ret = drmWaitVBlank(c->drm.fd, &vbl);
> +               if (ret) {
> +                       fprintf(stderr, "vblank event request failed: %d: %s\n",
> +                               ret, strerror(errno));
> +               }
> +       }
> +

Can't you just use the pageflip callback for this too?

>        return 0;
>  }
>
>  static void
> +vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec,
> +              void *data)
> +{
> +       struct drm_output *output = (struct drm_output *) data;
> +       struct drm_compositor *c =
> +               (struct drm_compositor *) output->base.compositor;
> +       struct weston_surface *surf, *next;
> +       struct drm_sprite *s;
> +
> +       /* Free the FBs for the sprites */
> +       wl_list_for_each(s, &output->sprite_list, output_link) {
> +               if (s->fb_id) {
> +                       drmModeRmFB(c->drm.fd, s->fb_id);
> +                       s->fb_id = 0;
> +               }
> +       }
> +
> +       /* Then send out buffer release messages */
> +       wl_list_for_each_safe(surf, next, &output->sprite_surfaces,
> +                             output_link) {
> +               weston_buffer_post_release(surf->buffer);
> +               wl_list_remove(&surf->output_link);
> +               wl_list_init(&surf->output_link);
> +       }
> +}
> +
> +static void
>  page_flip_handler(int fd, unsigned int frame,
>                  unsigned int sec, unsigned int usec, void *data)
>  {
> @@ -306,20 +377,17 @@ drm_assign_overlay_surface(struct weston_output *output_base,
>                return -1;
>        }
>
> -       fprintf(stderr, "displaying surface on sprite %d\n", s->plane_id);
> +       s->fb_id = fb_id;
> +       s->dest_x = es->x;
> +       s->dest_y = es->y;
> +       s->dest_w = es->width;
> +       s->dest_h = es->height;
> +       s->src_x = 0;
> +       s->src_y = 0;
> +       s->src_w = es->width;
> +       s->src_h = es->height;
>
> -       fprintf(stderr, "%d, %d, %d, %d, (%d,%d), %dx%d\n", c->drm.fd,
> -               s->plane_id, output->crtc_id, fb_id, es->x, es->y, es->width,
> -               es->height);
> -
> -       ret = drmModeSetPlane(c->drm.fd, s->plane_id, output->crtc_id, fb_id, 0,
> -                             es->x, es->y, es->width, es->height, 0, 0,
> -                             es->width, es->height);
> -       if (ret) {
> -               fprintf(stderr, "setplane failed %d: %s\n", ret,
> -                       strerror(errno));
> -               return -1;
> -       }
> +       wl_list_insert(&output->sprite_surfaces, &es->output_link);
>
>        return 0;
>  }
> @@ -328,13 +396,15 @@ static int
>  drm_assign_planes(struct weston_output *output)
>  {
>        struct weston_compositor *ec = output->compositor;
> -       struct weston_surface *es;
> +       struct weston_surface *es, *scanout = NULL;
>
>        es = container_of(ec->surface_list.next, struct weston_surface, link);
>
>        if (es->visual == WESTON_RGB_VISUAL) {
> -               if (!drm_output_prepare_scanout_surface(output, es))
> +               if (!drm_output_prepare_scanout_surface(output, es)) {
>                        drm_queue_scanout_surface(output, es);
> +                       scanout = es;
> +               }
>        }
>
>        /*
> @@ -482,6 +552,7 @@ on_drm_input(int fd, uint32_t mask, void *data)
>        memset(&evctx, 0, sizeof evctx);
>        evctx.version = DRM_EVENT_CONTEXT_VERSION;
>        evctx.page_flip_handler = page_flip_handler;
> +       evctx.vblank_handler = vblank_handler;
>        drmHandleEvent(fd, &evctx);
>
>        return 1;
> @@ -687,6 +758,7 @@ create_output_for_connector(struct drm_compositor *ec,
>        output->base.model = "unknown";
>        wl_list_init(&output->base.mode_list);
>        wl_list_init(&output->sprite_list);
> +       wl_list_init(&output->sprite_surfaces);
>
>        output->crtc_id = resources->crtcs[i];
>        ec->crtc_allocator |= (1 << output->crtc_id);
> diff --git a/src/compositor.c b/src/compositor.c
> index 348b4e7..cd3ad1a 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
> @@ -213,6 +213,7 @@ weston_surface_create(struct weston_compositor *compositor,
>
>        wl_list_init(&surface->link);
>        wl_list_init(&surface->buffer_link);
> +       wl_list_init(&surface->output_link);
>
>        glGenTextures(1, &surface->texture);
>        glBindTexture(GL_TEXTURE_2D, surface->texture);
> @@ -378,6 +379,7 @@ destroy_surface(struct wl_resource *resource)
>        weston_surface_damage_below(surface);
>
>        wl_list_remove(&surface->link);
> +       wl_list_remove(&surface->output_link);
>        weston_compositor_repick(compositor);
>
>        if (surface->saved_texture == 0)
> diff --git a/src/compositor.h b/src/compositor.h
> index e5e18a3..6716781 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -238,6 +238,7 @@ struct weston_surface {
>        int32_t pitch;
>        struct wl_list link;
>        struct wl_list buffer_link;
> +       struct wl_list output_link;
>        struct weston_transform *transform;
>        uint32_t alpha;
>        uint32_t visual;
> --
> 1.7.4.1
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list