[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