On Fri, Nov 09, 2012 at 02:19:05PM +0200, Ander Conselvan de Oliveira wrote: > 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.
Yea, that looks very good. I removed an unused 'int ret;' in vblank_handler(), otherwise applied as is. One nitpick, just for the record: I'd call it have_addfb2 and initialize it to 1 and clear it if addfb2 fails. That way we avoid the double negation in if (format && !compositor->no_addfb2) { which instead would read if (format && compositor->have_addfb2) { Anway, good work, thanks. Kristian > --- > 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 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel