compositor-drm: Use drm_fbs for the sprite code too

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.
dev
Ander Conselvan de Oliveira 12 years ago committed by Kristian Høgsberg
parent af696af2bb
commit 8d360b47ad
  1. 214
      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,16 @@ 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;
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 +556,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 +581,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 +591,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 +660,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 +1117,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 +1496,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 +1526,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 +1985,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);

Loading…
Cancel
Save