This makes drm_fb_get_from_bo() use drmModeAddFB2() if possible so that
drm_output_prepare_overlay_surface() can use this instead of keeping
track of the fbs and buffers itself.
---
 src/compositor-drm.c |  215 +++++++++++++++++++++-----------------------------
 1 file changed, 88 insertions(+), 127 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 9c9d54a..5137249 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -92,8 +92,9 @@ struct drm_compositor {
         * due to out of bounds dimensions, and then mistakenly set
         * sprites_are_broken:
         */
-       int32_t min_width, max_width;
-       int32_t min_height, max_height;
+       uint32_t min_width, max_width;
+       uint32_t min_height, max_height;
+       int no_addfb2;
 
        struct wl_list sprite_list;
        int sprites_are_broken;
@@ -149,19 +150,12 @@ struct drm_output {
 struct drm_sprite {
        struct wl_list link;
 
-       uint32_t fb_id;
-       uint32_t pending_fb_id;
-       struct weston_surface *surface;
-       struct weston_surface *pending_surface;
        struct weston_plane plane;
 
+       struct drm_fb *current, *next;
        struct drm_output *output;
-
        struct drm_compositor *compositor;
 
-       struct wl_listener destroy_listener;
-       struct wl_listener pending_destroy_listener;
-
        uint32_t possible_crtcs;
        uint32_t plane_id;
        uint32_t count_formats;
@@ -222,12 +216,11 @@ drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
 }
 
 static struct drm_fb *
-drm_fb_get_from_bo(struct gbm_bo *bo)
+drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_compositor *compositor)
 {
        struct drm_fb *fb = gbm_bo_get_user_data(bo);
-       struct drm_compositor *compositor =
-               (struct drm_compositor *) output->base.compositor;
-       uint32_t width, height, stride, handle;
+       uint32_t width, height, stride, handle, format;
+       uint32_t handles[4], pitches[4], offsets[4];
        int ret;
 
        if (fb)
@@ -244,17 +237,48 @@ drm_fb_get_from_bo(struct gbm_bo *bo)
        stride = gbm_bo_get_stride(bo);
        handle = gbm_bo_get_handle(bo).u32;
 
-       ret = drmModeAddFB(compositor->drm.fd, width, height, 24, 32,
-                          stride, handle, &fb->fb_id);
+       if (compositor->min_width > width || width > compositor->max_width ||
+           compositor->min_height > height ||
+           height > compositor->max_height) {
+               weston_log("bo geometry out of bounds\n");
+               goto err_free;
+       }
+
+       ret = -1;
+
+       format = gbm_bo_get_format(bo);
+
+       if (format && !compositor->no_addfb2) {
+               handles[0] = handle;
+               pitches[0] = stride;
+               offsets[0] = 0;
+
+               ret = drmModeAddFB2(compositor->drm.fd, width, height,
+                                   format, handles, pitches, offsets,
+                                   &fb->fb_id, 0);
+               if (ret) {
+                       weston_log("addfb2 failed: %m\n");
+                       compositor->no_addfb2 = 1;
+                       compositor->sprites_are_broken = 1;
+               }
+       }
+
+       if (ret)
+               ret = drmModeAddFB(compositor->drm.fd, width, height, 24, 32,
+                                  stride, handle, &fb->fb_id);
+
        if (ret) {
                weston_log("failed to create kms fb: %m\n");
-               free(fb);
-               return NULL;
+               goto err_free;
        }
 
        gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback);
 
        return fb;
+
+err_free:
+       free(fb);
+       return NULL;
 }
 
 static void
@@ -266,6 +290,20 @@ fb_handle_buffer_destroy(struct wl_listener *listener, 
void *data)
        fb->buffer = NULL;
 }
 
+static void
+drm_fb_set_buffer(struct drm_fb *fb, struct wl_buffer *buffer)
+{
+       assert(fb->buffer == NULL);
+
+       fb->is_client_buffer = 1;
+       fb->buffer = buffer;
+       fb->buffer->busy_count++;
+       fb->buffer_destroy_listener.notify = fb_handle_buffer_destroy;
+
+       wl_signal_add(&fb->buffer->resource.destroy_signal,
+                     &fb->buffer_destroy_listener);
+}
+
 static struct weston_plane *
 drm_output_prepare_scanout_surface(struct weston_output *_output,
                                   struct weston_surface *es)
@@ -298,19 +336,13 @@ drm_output_prepare_scanout_surface(struct weston_output 
*_output,
                return NULL;
        }
 
-       output->next = drm_fb_get_from_bo(bo);
+       output->next = drm_fb_get_from_bo(bo, c);
        if (!output->next) {
                gbm_bo_destroy(bo);
                return NULL;
        }
 
-       output->next->is_client_buffer = 1;
-       output->next->buffer = es->buffer;
-       output->next->buffer->busy_count++;
-       output->next->buffer_destroy_listener.notify = fb_handle_buffer_destroy;
-
-       wl_signal_add(&output->next->buffer->resource.destroy_signal,
-                     &output->next->buffer_destroy_listener);
+       drm_fb_set_buffer(output->next, es->buffer);
 
        return &output->fb_plane;
 }
@@ -318,10 +350,11 @@ drm_output_prepare_scanout_surface(struct weston_output 
*_output,
 static void
 drm_output_render(struct drm_output *output, pixman_region32_t *damage)
 {
-       struct weston_compositor *ec = output->base.compositor;
+       struct drm_compositor *c =
+               (struct drm_compositor *) output->base.compositor;
        struct gbm_bo *bo;
 
-       ec->renderer->repaint_output(&output->base, damage);
+       c->base.renderer->repaint_output(&output->base, damage);
 
        bo = gbm_surface_lock_front_buffer(output->surface);
        if (!bo) {
@@ -329,7 +362,7 @@ drm_output_render(struct drm_output *output, 
pixman_region32_t *damage)
                return;
        }
 
-       output->next = drm_fb_get_from_bo(bo);
+       output->next = drm_fb_get_from_bo(bo, c);
        if (!output->next) {
                weston_log("failed to get drm_fb for bo\n");
                gbm_surface_release_buffer(output->surface, bo);
@@ -380,21 +413,21 @@ drm_output_repaint(struct weston_output *output_base,
         * Now, update all the sprite surfaces
         */
        wl_list_for_each(s, &compositor->sprite_list, link) {
-               uint32_t flags = 0;
+               uint32_t flags = 0, fb_id = 0;
                drmVBlank vbl = {
                        .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
                        .request.sequence = 1,
                };
 
-               if ((!s->fb_id && !s->pending_fb_id) ||
+               if ((!s->current && !s->next) ||
                    !drm_sprite_crtc_supported(output_base, s->possible_crtcs))
                        continue;
 
+               if (s->next && !compositor->sprites_hidden)
+                       fb_id = s->next->fb_id;
+
                ret = drmModeSetPlane(compositor->drm.fd, s->plane_id,
-                                     output->crtc_id,
-                                     compositor->sprites_hidden ?
-                                     0 : s->pending_fb_id,
-                                     flags,
+                                     output->crtc_id, fb_id, flags,
                                      s->dest_x, s->dest_y,
                                      s->dest_w, s->dest_h,
                                      s->src_x, s->src_y,
@@ -429,29 +462,17 @@ vblank_handler(int fd, unsigned int frame, unsigned int 
sec, unsigned int usec,
               void *data)
 {
        struct drm_sprite *s = (struct drm_sprite *)data;
-       struct drm_compositor *c = s->compositor;
        struct drm_output *output = s->output;
        uint32_t msecs;
+       int ret;
 
        output->vblank_pending = 0;
 
-       if (s->surface) {
-               weston_buffer_post_release(s->surface->buffer);
-               wl_list_remove(&s->destroy_listener.link);
-               s->surface = NULL;
-               drmModeRmFB(c->drm.fd, s->fb_id);
-               s->fb_id = 0;
-       }
+       if (s->current)
+               gbm_bo_destroy(s->current->bo);
 
-       if (s->pending_surface) {
-               wl_list_remove(&s->pending_destroy_listener.link);
-               
wl_signal_add(&s->pending_surface->buffer->resource.destroy_signal,
-                             &s->destroy_listener);
-               s->surface = s->pending_surface;
-               s->pending_surface = NULL;
-               s->fb_id = s->pending_fb_id;
-               s->pending_fb_id = 0;
-       }
+       s->current = s->next;
+       s->next = NULL;
 
        if (!output->page_flip_pending) {
                msecs = sec * 1000 + usec / 1000;
@@ -536,16 +557,11 @@ drm_output_prepare_overlay_surface(struct weston_output 
*output_base,
        struct drm_compositor *c =(struct drm_compositor *) ec;
        struct drm_sprite *s;
        int found = 0;
-       EGLint handle, stride;
        struct gbm_bo *bo;
-       uint32_t fb_id = 0;
-       uint32_t handles[4], pitches[4], offsets[4];
-       int ret = 0;
        pixman_region32_t dest_rect, src_rect;
        pixman_box32_t *box;
        uint32_t format;
        wl_fixed_t sx1, sy1, sx2, sy2;
-       int32_t width, height;
 
        if (c->sprites_are_broken)
                return NULL;
@@ -566,7 +582,7 @@ drm_output_prepare_overlay_surface(struct weston_output 
*output_base,
                if (!drm_sprite_crtc_supported(output_base, s->possible_crtcs))
                        continue;
 
-               if (!s->pending_fb_id) {
+               if (!s->next) {
                        found = 1;
                        break;
                }
@@ -576,49 +592,25 @@ drm_output_prepare_overlay_surface(struct weston_output 
*output_base,
        if (!found)
                return NULL;
 
-       width = es->geometry.width;
-       height = es->geometry.height;
-
-       /* If geometry is out of bounds, don't even bother trying because
-        * we know the AddFB2() call will fail:
-        */
-       if (c->min_width > width || width > c->max_width ||
-           c->min_height > height || height > c->max_height)
-               return NULL;
-
        bo = gbm_bo_import(c->gbm, GBM_BO_IMPORT_WL_BUFFER,
                           es->buffer, GBM_BO_USE_SCANOUT);
        if (!bo)
                return NULL;
 
        format = gbm_bo_get_format(bo);
-       handle = gbm_bo_get_handle(bo).s32;
-       stride = gbm_bo_get_stride(bo);
-
-       gbm_bo_destroy(bo);
-
-       if (!drm_surface_format_supported(s, format))
-               return NULL;
 
-       if (!handle)
+       if (!drm_surface_format_supported(s, format)) {
+               gbm_bo_destroy(bo);
                return NULL;
+       }
 
-       handles[0] = handle;
-       pitches[0] = stride;
-       offsets[0] = 0;
-
-       ret = drmModeAddFB2(c->drm.fd, width, height,
-                           format, handles, pitches, offsets,
-                           &fb_id, 0);
-       if (ret) {
-               weston_log("addfb2 failed: %d\n", ret);
-               c->sprites_are_broken = 1;
+       s->next = drm_fb_get_from_bo(bo, c);
+       if (!s->next) {
+               gbm_bo_destroy(bo);
                return NULL;
        }
 
-       s->pending_fb_id = fb_id;
-       s->pending_surface = es;
-       es->buffer->busy_count++;
+       drm_fb_set_buffer(s->next, es->buffer);
 
        box = pixman_region32_extents(&es->transform.boundingbox);
        s->plane.x = box->x1;
@@ -669,9 +661,6 @@ drm_output_prepare_overlay_surface(struct weston_output 
*output_base,
        s->src_h = (sy2 - sy1) << 8;
        pixman_region32_fini(&src_rect);
 
-       wl_signal_add(&es->buffer->resource.destroy_signal,
-                     &s->pending_destroy_listener);
-
        return &s->plane;
 }
 
@@ -1129,32 +1118,6 @@ drm_subpixel_to_wayland(int drm_value)
        }
 }
 
-static void
-sprite_handle_buffer_destroy(struct wl_listener *listener, void *data)
-{
-       struct drm_sprite *sprite =
-               container_of(listener, struct drm_sprite,
-                            destroy_listener);
-       struct drm_compositor *compositor = sprite->compositor;
-
-       sprite->surface = NULL;
-       drmModeRmFB(compositor->drm.fd, sprite->fb_id);
-       sprite->fb_id = 0;
-}
-
-static void
-sprite_handle_pending_buffer_destroy(struct wl_listener *listener, void *data)
-{
-       struct drm_sprite *sprite =
-               container_of(listener, struct drm_sprite,
-                            pending_destroy_listener);
-       struct drm_compositor *compositor = sprite->compositor;
-
-       sprite->pending_surface = NULL;
-       drmModeRmFB(compositor->drm.fd, sprite->pending_fb_id);
-       sprite->pending_fb_id = 0;
-}
-
 /* returns a value between 0-255 range, where higher is brighter */
 static uint32_t
 drm_get_backlight(struct drm_output *output)
@@ -1534,13 +1497,8 @@ create_sprites(struct drm_compositor *ec)
 
                sprite->possible_crtcs = plane->possible_crtcs;
                sprite->plane_id = plane->plane_id;
-               sprite->surface = NULL;
-               sprite->pending_surface = NULL;
-               sprite->fb_id = 0;
-               sprite->pending_fb_id = 0;
-               sprite->destroy_listener.notify = sprite_handle_buffer_destroy;
-               sprite->pending_destroy_listener.notify =
-                       sprite_handle_pending_buffer_destroy;
+               sprite->current = NULL;
+               sprite->next = NULL;
                sprite->compositor = ec;
                sprite->count_formats = plane->count_formats;
                memcpy(sprite->formats, plane->formats,
@@ -1569,7 +1527,10 @@ destroy_sprites(struct drm_compositor *compositor)
                                sprite->plane_id,
                                output->crtc_id, 0, 0,
                                0, 0, 0, 0, 0, 0, 0, 0);
-               drmModeRmFB(compositor->drm.fd, sprite->fb_id);
+               if (sprite->current)
+                       gbm_bo_destroy(sprite->current->bo);
+               if (sprite->next)
+                       gbm_bo_destroy(sprite->next->bo);
                weston_plane_release(&sprite->plane);
                free(sprite);
        }
@@ -2025,8 +1986,8 @@ drm_destroy(struct weston_compositor *ec)
        eglTerminate(ec->egl_display);
        eglReleaseThread();
 
-       gbm_device_destroy(d->gbm);
        destroy_sprites(d);
+       gbm_device_destroy(d->gbm);
        if (weston_launcher_drm_set_master(&d->base, d->drm.fd, 0) < 0)
                weston_log("failed to drop master: %m\n");
        tty_destroy(d->tty);
-- 
1.7.10.4

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to