2 * Copyright © 2008-2011 Kristian Høgsberg
3 * Copyright © 2011 Intel Corporation
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36 #include <linux/input.h>
44 #include <xf86drmMode.h>
45 #include <drm_fourcc.h>
50 #include "compositor.h"
51 #include "compositor-drm.h"
52 #include "shared/helpers.h"
53 #include "shared/timespec-util.h"
54 #include "gl-renderer.h"
55 #include "weston-egl-ext.h"
56 #include "pixman-renderer.h"
57 #include "pixel-formats.h"
58 #include "libbacklight.h"
59 #include "libinput-seat.h"
60 #include "launcher-util.h"
61 #include "vaapi-recorder.h"
62 #include "presentation-time-server-protocol.h"
63 #include "linux-dmabuf.h"
64 #include "linux-dmabuf-unstable-v1-server-protocol.h"
66 #ifndef DRM_CAP_TIMESTAMP_MONOTONIC
67 #define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
70 #ifndef DRM_CAP_CURSOR_WIDTH
71 #define DRM_CAP_CURSOR_WIDTH 0x8
74 #ifndef DRM_CAP_CURSOR_HEIGHT
75 #define DRM_CAP_CURSOR_HEIGHT 0x9
78 #ifndef GBM_BO_USE_CURSOR
79 #define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64
83 struct weston_backend base;
84 struct weston_compositor *compositor;
87 struct wl_event_source *drm_source;
89 struct udev_monitor *udev_monitor;
90 struct wl_event_source *udev_drm_source;
97 struct gbm_device *gbm;
98 struct wl_listener session_listener;
101 /* we need these parameters in order to not fail drmModeAddFB2()
102 * due to out of bounds dimensions, and then mistakenly set
103 * sprites_are_broken:
105 int min_width, max_width;
106 int min_height, max_height;
109 struct wl_list sprite_list;
110 int sprites_are_broken;
113 int cursors_are_broken;
117 struct udev_input input;
119 int32_t cursor_width;
120 int32_t cursor_height;
123 uint32_t pageflip_timeout;
127 struct weston_mode base;
128 drmModeModeInfo mode_info;
132 BUFFER_INVALID = 0, /**< never used */
133 BUFFER_CLIENT, /**< directly sourced from client */
134 BUFFER_PIXMAN_DUMB, /**< internal Pixman rendering */
135 BUFFER_GBM_SURFACE, /**< internal EGL rendering */
136 BUFFER_CURSOR, /**< internal cursor buffer */
140 enum drm_fb_type type;
144 uint32_t fb_id, stride, handle, size;
145 const struct pixel_format_info *format;
148 struct weston_buffer_reference buffer_ref;
150 /* Used by gbm fbs */
152 struct gbm_surface *gbm_surface;
154 /* Used by dumb fbs */
160 char monitor_name[13];
162 char serial_number[13];
166 * A plane represents one buffer, positioned within a CRTC, and stacked
167 * relative to other planes on the same CRTC.
169 * Each CRTC has a 'primary plane', which use used to display the classic
170 * framebuffer contents, as accessed through the legacy drmModeSetCrtc
171 * call (which combines setting the CRTC's actual physical mode, and the
172 * properties of the primary plane).
174 * The cursor plane also has its own alternate legacy API.
176 * Other planes are used opportunistically to display content we do not
177 * wish to blit into the primary plane. These non-primary/cursor planes
178 * are referred to as 'sprites'.
183 struct weston_plane base;
185 struct drm_output *output;
186 struct drm_backend *backend;
188 uint32_t possible_crtcs;
190 uint32_t count_formats;
192 /* The last framebuffer submitted to the kernel for this plane. */
193 struct drm_fb *fb_current;
194 /* The previously-submitted framebuffer, where the hardware has not
195 * yet acknowledged display of fb_current. */
196 struct drm_fb *fb_last;
197 /* Framebuffer we are going to submit to the kernel when the current
198 * repaint is flushed. */
199 struct drm_fb *fb_pending;
201 int32_t src_x, src_y;
202 uint32_t src_w, src_h;
203 uint32_t dest_x, dest_y;
204 uint32_t dest_w, dest_h;
210 struct weston_output base;
211 drmModeConnector *connector;
213 uint32_t crtc_id; /* object ID to pass to DRM functions */
214 int pipe; /* index of CRTC in resource array / bitmasks */
215 uint32_t connector_id;
216 drmModeCrtcPtr original_crtc;
217 struct drm_edid edid;
218 drmModePropertyPtr dpms_prop;
221 struct backlight *backlight;
224 int page_flip_pending;
228 struct drm_fb *gbm_cursor_fb[2];
229 struct weston_plane cursor_plane;
230 struct weston_view *cursor_view;
233 struct gbm_surface *gbm_surface;
236 struct weston_plane fb_plane;
238 /* The last framebuffer submitted to the kernel for this CRTC. */
239 struct drm_fb *fb_current;
240 /* The previously-submitted framebuffer, where the hardware has not
241 * yet acknowledged display of fb_current. */
242 struct drm_fb *fb_last;
243 /* Framebuffer we are going to submit to the kernel when the current
244 * repaint is flushed. */
245 struct drm_fb *fb_pending;
247 struct drm_fb *dumb[2];
248 pixman_image_t *image[2];
250 pixman_region32_t previous_damage;
252 struct vaapi_recorder *recorder;
253 struct wl_listener recorder_frame_listener;
255 struct wl_event_source *pageflip_timer;
258 static struct gl_renderer_interface *gl_renderer;
260 static const char default_seat[] = "seat0";
262 static inline struct drm_output *
263 to_drm_output(struct weston_output *base)
265 return container_of(base, struct drm_output, base);
268 static inline struct drm_backend *
269 to_drm_backend(struct weston_compositor *base)
271 return container_of(base->backend, struct drm_backend, base);
275 pageflip_timeout(void *data) {
277 * Our timer just went off, that means we're not receiving drm
278 * page flip events anymore for that output. Let's gracefully exit
279 * weston with a return value so devs can debug what's going on.
281 struct drm_output *output = data;
282 struct weston_compositor *compositor = output->base.compositor;
284 weston_log("Pageflip timeout reached on output %s, your "
285 "driver is probably buggy! Exiting.\n",
287 weston_compositor_exit_with_code(compositor, EXIT_FAILURE);
292 /* Creates the pageflip timer. Note that it isn't armed by default */
294 drm_output_pageflip_timer_create(struct drm_output *output)
296 struct wl_event_loop *loop = NULL;
297 struct weston_compositor *ec = output->base.compositor;
299 loop = wl_display_get_event_loop(ec->wl_display);
301 output->pageflip_timer = wl_event_loop_add_timer(loop,
305 if (output->pageflip_timer == NULL) {
306 weston_log("creating drm pageflip timer failed: %m\n");
314 drm_output_set_cursor(struct drm_output *output);
317 drm_output_update_msc(struct drm_output *output, unsigned int seq);
320 drm_plane_crtc_supported(struct drm_output *output, struct drm_plane *plane)
322 return !!(plane->possible_crtcs & (1 << output->pipe));
325 static struct drm_output *
326 drm_output_find_by_crtc(struct drm_backend *b, uint32_t crtc_id)
328 struct drm_output *output;
330 wl_list_for_each(output, &b->compositor->output_list, base.link) {
331 if (output->crtc_id == crtc_id)
335 wl_list_for_each(output, &b->compositor->pending_output_list,
337 if (output->crtc_id == crtc_id)
344 static struct drm_output *
345 drm_output_find_by_connector(struct drm_backend *b, uint32_t connector_id)
347 struct drm_output *output;
349 wl_list_for_each(output, &b->compositor->output_list, base.link) {
350 if (output->connector_id == connector_id)
354 wl_list_for_each(output, &b->compositor->pending_output_list,
356 if (output->connector_id == connector_id)
364 drm_fb_destroy(struct drm_fb *fb)
367 drmModeRmFB(fb->fd, fb->fb_id);
368 weston_buffer_reference(&fb->buffer_ref, NULL);
373 drm_fb_destroy_dumb(struct drm_fb *fb)
375 struct drm_mode_destroy_dumb destroy_arg;
377 assert(fb->type == BUFFER_PIXMAN_DUMB);
379 if (fb->map && fb->size > 0)
380 munmap(fb->map, fb->size);
382 memset(&destroy_arg, 0, sizeof(destroy_arg));
383 destroy_arg.handle = fb->handle;
384 drmIoctl(fb->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
390 drm_fb_destroy_gbm(struct gbm_bo *bo, void *data)
392 struct drm_fb *fb = data;
394 assert(fb->type == BUFFER_GBM_SURFACE || fb->type == BUFFER_CLIENT ||
395 fb->type == BUFFER_CURSOR);
399 static struct drm_fb *
400 drm_fb_create_dumb(struct drm_backend *b, int width, int height,
406 struct drm_mode_create_dumb create_arg;
407 struct drm_mode_destroy_dumb destroy_arg;
408 struct drm_mode_map_dumb map_arg;
410 fb = zalloc(sizeof *fb);
416 fb->format = pixel_format_get_info(format);
418 weston_log("failed to look up format 0x%lx\n",
419 (unsigned long) format);
423 if (!fb->format->depth || !fb->format->bpp) {
424 weston_log("format 0x%lx is not compatible with dumb buffers\n",
425 (unsigned long) format);
429 memset(&create_arg, 0, sizeof create_arg);
430 create_arg.bpp = fb->format->bpp;
431 create_arg.width = width;
432 create_arg.height = height;
434 ret = drmIoctl(b->drm.fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg);
438 fb->type = BUFFER_PIXMAN_DUMB;
439 fb->handle = create_arg.handle;
440 fb->stride = create_arg.pitch;
441 fb->size = create_arg.size;
449 uint32_t handles[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 };
451 handles[0] = fb->handle;
452 pitches[0] = fb->stride;
455 ret = drmModeAddFB2(b->drm.fd, width, height,
457 handles, pitches, offsets,
460 weston_log("addfb2 failed: %m\n");
466 ret = drmModeAddFB(b->drm.fd, width, height,
467 fb->format->depth, fb->format->bpp,
468 fb->stride, fb->handle, &fb->fb_id);
474 memset(&map_arg, 0, sizeof map_arg);
475 map_arg.handle = fb->handle;
476 ret = drmIoctl(fb->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_arg);
480 fb->map = mmap(NULL, fb->size, PROT_WRITE,
481 MAP_SHARED, b->drm.fd, map_arg.offset);
482 if (fb->map == MAP_FAILED)
488 drmModeRmFB(b->drm.fd, fb->fb_id);
490 memset(&destroy_arg, 0, sizeof(destroy_arg));
491 destroy_arg.handle = create_arg.handle;
492 drmIoctl(b->drm.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
498 static struct drm_fb *
499 drm_fb_ref(struct drm_fb *fb)
505 static struct drm_fb *
506 drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend,
507 uint32_t format, enum drm_fb_type type)
509 struct drm_fb *fb = gbm_bo_get_user_data(bo);
510 uint32_t handles[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 };
514 assert(fb->type == type);
515 return drm_fb_ref(fb);
518 fb = zalloc(sizeof *fb);
526 fb->width = gbm_bo_get_width(bo);
527 fb->height = gbm_bo_get_height(bo);
528 fb->stride = gbm_bo_get_stride(bo);
529 fb->handle = gbm_bo_get_handle(bo).u32;
530 fb->format = pixel_format_get_info(format);
531 fb->size = fb->stride * fb->height;
532 fb->fd = backend->drm.fd;
535 weston_log("couldn't look up format 0x%lx\n",
536 (unsigned long) format);
540 if (backend->min_width > fb->width ||
541 fb->width > backend->max_width ||
542 backend->min_height > fb->height ||
543 fb->height > backend->max_height) {
544 weston_log("bo geometry out of bounds\n");
550 if (format && !backend->no_addfb2) {
551 handles[0] = fb->handle;
552 pitches[0] = fb->stride;
555 ret = drmModeAddFB2(backend->drm.fd, fb->width, fb->height,
556 format, handles, pitches, offsets,
559 weston_log("addfb2 failed: %m\n");
560 backend->no_addfb2 = 1;
561 backend->sprites_are_broken = 1;
565 if (ret && fb->format->depth && fb->format->bpp)
566 ret = drmModeAddFB(backend->drm.fd, fb->width, fb->height,
567 fb->format->depth, fb->format->bpp,
568 fb->stride, fb->handle, &fb->fb_id);
571 weston_log("failed to create kms fb: %m\n");
575 gbm_bo_set_user_data(bo, fb, drm_fb_destroy_gbm);
585 drm_fb_set_buffer(struct drm_fb *fb, struct weston_buffer *buffer)
587 assert(fb->buffer_ref.buffer == NULL);
588 assert(fb->type == BUFFER_CLIENT);
589 weston_buffer_reference(&fb->buffer_ref, buffer);
593 drm_fb_unref(struct drm_fb *fb)
598 assert(fb->refcnt > 0);
599 if (--fb->refcnt > 0)
603 case BUFFER_PIXMAN_DUMB:
604 drm_fb_destroy_dumb(fb);
608 gbm_bo_destroy(fb->bo);
610 case BUFFER_GBM_SURFACE:
611 gbm_surface_release_buffer(fb->gbm_surface, fb->bo);
620 drm_view_transform_supported(struct weston_view *ev)
622 return !ev->transform.enabled ||
623 (ev->transform.matrix.type < WESTON_MATRIX_TRANSFORM_ROTATE);
627 drm_output_check_scanout_format(struct drm_output *output,
628 struct weston_surface *es, struct gbm_bo *bo)
633 format = gbm_bo_get_format(bo);
635 if (format == GBM_FORMAT_ARGB8888) {
636 /* We can scanout an ARGB buffer if the surface's
637 * opaque region covers the whole output, but we have
638 * to use XRGB as the KMS format code. */
639 pixman_region32_init_rect(&r, 0, 0,
641 output->base.height);
642 pixman_region32_subtract(&r, &r, &es->opaque);
644 if (!pixman_region32_not_empty(&r))
645 format = GBM_FORMAT_XRGB8888;
647 pixman_region32_fini(&r);
650 if (output->gbm_format == format)
656 static struct weston_plane *
657 drm_output_prepare_scanout_view(struct drm_output *output,
658 struct weston_view *ev)
660 struct drm_backend *b = to_drm_backend(output->base.compositor);
661 struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
662 struct weston_buffer_viewport *viewport = &ev->surface->buffer_viewport;
666 /* Don't import buffers which span multiple outputs. */
667 if (ev->output_mask != (1u << output->base.id))
670 /* We use GBM to import buffers. */
676 if (wl_shm_buffer_get(buffer->resource))
679 /* Make sure our view is exactly compatible with the output. */
680 if (ev->geometry.x != output->base.x ||
681 ev->geometry.y != output->base.y)
683 if (buffer->width != output->base.current_mode->width ||
684 buffer->height != output->base.current_mode->height)
687 if (ev->transform.enabled)
689 if (ev->geometry.scissor_enabled)
691 if (viewport->buffer.transform != output->base.transform)
693 if (viewport->buffer.scale != output->base.current_scale)
695 if (!drm_view_transform_supported(ev))
698 if (ev->alpha != 1.0f)
701 bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER,
702 buffer->resource, GBM_BO_USE_SCANOUT);
704 /* Unable to use the buffer for scanout */
708 format = drm_output_check_scanout_format(output, ev->surface, bo);
714 output->fb_pending = drm_fb_get_from_bo(bo, b, format, BUFFER_CLIENT);
715 if (!output->fb_pending) {
720 drm_fb_set_buffer(output->fb_pending, buffer);
722 return &output->fb_plane;
725 static struct drm_fb *
726 drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage)
728 struct drm_backend *b = to_drm_backend(output->base.compositor);
732 output->base.compositor->renderer->repaint_output(&output->base,
735 bo = gbm_surface_lock_front_buffer(output->gbm_surface);
737 weston_log("failed to lock front buffer: %m\n");
741 ret = drm_fb_get_from_bo(bo, b, output->gbm_format, BUFFER_GBM_SURFACE);
743 weston_log("failed to get drm_fb for bo\n");
744 gbm_surface_release_buffer(output->gbm_surface, bo);
747 ret->gbm_surface = output->gbm_surface;
752 static struct drm_fb *
753 drm_output_render_pixman(struct drm_output *output, pixman_region32_t *damage)
755 struct weston_compositor *ec = output->base.compositor;
756 pixman_region32_t total_damage, previous_damage;
758 pixman_region32_init(&total_damage);
759 pixman_region32_init(&previous_damage);
761 pixman_region32_copy(&previous_damage, damage);
763 pixman_region32_union(&total_damage, damage, &output->previous_damage);
764 pixman_region32_copy(&output->previous_damage, &previous_damage);
766 output->current_image ^= 1;
768 pixman_renderer_output_set_buffer(&output->base,
769 output->image[output->current_image]);
771 ec->renderer->repaint_output(&output->base, &total_damage);
773 pixman_region32_fini(&total_damage);
774 pixman_region32_fini(&previous_damage);
776 return drm_fb_ref(output->dumb[output->current_image]);
780 drm_output_render(struct drm_output *output, pixman_region32_t *damage)
782 struct weston_compositor *c = output->base.compositor;
783 struct drm_backend *b = to_drm_backend(c);
786 /* If we already have a client buffer promoted to scanout, then we don't
788 if (output->fb_pending)
792 fb = drm_output_render_pixman(output, damage);
794 fb = drm_output_render_gl(output, damage);
798 output->fb_pending = fb;
800 pixman_region32_subtract(&c->primary_plane.damage,
801 &c->primary_plane.damage, damage);
805 drm_output_set_gamma(struct weston_output *output_base,
806 uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b)
809 struct drm_output *output = to_drm_output(output_base);
810 struct drm_backend *backend =
811 to_drm_backend(output->base.compositor);
814 if (output_base->gamma_size != size)
816 if (!output->original_crtc)
819 rc = drmModeCrtcSetGamma(backend->drm.fd,
823 weston_log("set gamma failed: %m\n");
826 /* Determine the type of vblank synchronization to use for the output.
828 * The pipe parameter indicates which CRTC is in use. Knowing this, we
829 * can determine which vblank sequence type to use for it. Traditional
830 * cards had only two CRTCs, with CRTC 0 using no special flags, and
831 * CRTC 1 using DRM_VBLANK_SECONDARY. The first bit of the pipe
832 * parameter indicates this.
834 * Bits 1-5 of the pipe parameter are 5 bit wide pipe number between
835 * 0-31. If this is non-zero it indicates we're dealing with a
836 * multi-gpu situation and we need to calculate the vblank sync
837 * using DRM_BLANK_HIGH_CRTC_MASK.
840 drm_waitvblank_pipe(struct drm_output *output)
842 if (output->pipe > 1)
843 return (output->pipe << DRM_VBLANK_HIGH_CRTC_SHIFT) &
844 DRM_VBLANK_HIGH_CRTC_MASK;
845 else if (output->pipe > 0)
846 return DRM_VBLANK_SECONDARY;
852 drm_output_repaint(struct weston_output *output_base,
853 pixman_region32_t *damage,
856 struct drm_output *output = to_drm_output(output_base);
857 struct drm_backend *backend =
858 to_drm_backend(output->base.compositor);
860 struct drm_mode *mode;
863 if (output->disable_pending || output->destroy_pending)
866 assert(!output->fb_last);
868 /* If disable_planes is set then assign_planes() wasn't
869 * called for this render, so we could still have a stale
870 * cursor plane set up.
872 if (output->base.disable_planes) {
873 output->cursor_view = NULL;
874 output->cursor_plane.x = INT32_MIN;
875 output->cursor_plane.y = INT32_MIN;
878 drm_output_render(output, damage);
879 if (!output->fb_pending)
882 mode = container_of(output->base.current_mode, struct drm_mode, base);
883 if (!output->fb_current ||
884 output->fb_current->stride != output->fb_pending->stride) {
885 ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id,
886 output->fb_pending->fb_id, 0, 0,
887 &output->connector_id, 1,
890 weston_log("set mode failed: %m\n");
893 output_base->set_dpms(output_base, WESTON_DPMS_ON);
896 if (drmModePageFlip(backend->drm.fd, output->crtc_id,
897 output->fb_pending->fb_id,
898 DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
899 weston_log("queueing pageflip failed: %m\n");
903 output->fb_last = output->fb_current;
904 output->fb_current = output->fb_pending;
905 output->fb_pending = NULL;
907 assert(!output->page_flip_pending);
908 output->page_flip_pending = 1;
910 if (output->pageflip_timer)
911 wl_event_source_timer_update(output->pageflip_timer,
912 backend->pageflip_timeout);
914 drm_output_set_cursor(output);
917 * Now, update all the sprite surfaces
919 wl_list_for_each(s, &backend->sprite_list, link) {
920 uint32_t flags = 0, fb_id = 0;
922 .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
923 .request.sequence = 1,
926 /* XXX: Set output much earlier, so we don't attempt to place
927 * planes on entirely the wrong output. */
928 if ((!s->fb_current && !s->fb_pending) ||
929 !drm_plane_crtc_supported(output, s))
932 if (s->fb_pending && !backend->sprites_hidden)
933 fb_id = s->fb_pending->fb_id;
935 ret = drmModeSetPlane(backend->drm.fd, s->plane_id,
936 output->crtc_id, fb_id, flags,
937 s->dest_x, s->dest_y,
938 s->dest_w, s->dest_h,
942 weston_log("setplane failed: %d: %s\n",
943 ret, strerror(errno));
945 vbl.request.type |= drm_waitvblank_pipe(output);
948 * Queue a vblank signal so we know when the surface
949 * becomes active on the display or has been replaced.
951 vbl.request.signal = (unsigned long)s;
952 ret = drmWaitVBlank(backend->drm.fd, &vbl);
954 weston_log("vblank event request failed: %d: %s\n",
955 ret, strerror(errno));
959 s->fb_last = s->fb_current;
960 s->fb_current = s->fb_pending;
961 s->fb_pending = NULL;
962 output->vblank_pending++;
968 output->cursor_view = NULL;
969 if (output->fb_pending) {
970 drm_fb_unref(output->fb_pending);
971 output->fb_pending = NULL;
978 drm_output_start_repaint_loop(struct weston_output *output_base)
980 struct drm_output *output = to_drm_output(output_base);
981 struct drm_backend *backend =
982 to_drm_backend(output_base->compositor);
984 struct timespec ts, tnow;
985 struct timespec vbl2now;
986 int64_t refresh_nsec;
989 .request.type = DRM_VBLANK_RELATIVE,
990 .request.sequence = 0,
994 if (output->disable_pending || output->destroy_pending)
997 if (!output->fb_current) {
998 /* We can't page flip if there's no mode set */
1002 /* Try to get current msc and timestamp via instant query */
1003 vbl.request.type |= drm_waitvblank_pipe(output);
1004 ret = drmWaitVBlank(backend->drm.fd, &vbl);
1006 /* Error ret or zero timestamp means failure to get valid timestamp */
1007 if ((ret == 0) && (vbl.reply.tval_sec > 0 || vbl.reply.tval_usec > 0)) {
1008 ts.tv_sec = vbl.reply.tval_sec;
1009 ts.tv_nsec = vbl.reply.tval_usec * 1000;
1011 /* Valid timestamp for most recent vblank - not stale?
1012 * Stale ts could happen on Linux 3.17+, so make sure it
1013 * is not older than 1 refresh duration since now.
1015 weston_compositor_read_presentation_clock(backend->compositor,
1017 timespec_sub(&vbl2now, &tnow, &ts);
1019 millihz_to_nsec(output->base.current_mode->refresh);
1020 if (timespec_to_nsec(&vbl2now) < refresh_nsec) {
1021 drm_output_update_msc(output, vbl.reply.sequence);
1022 weston_output_finish_frame(output_base, &ts,
1023 WP_PRESENTATION_FEEDBACK_INVALID);
1028 /* Immediate query didn't provide valid timestamp.
1029 * Use pageflip fallback.
1031 fb_id = output->fb_current->fb_id;
1033 assert(!output->page_flip_pending);
1034 assert(!output->fb_last);
1036 if (drmModePageFlip(backend->drm.fd, output->crtc_id, fb_id,
1037 DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
1038 weston_log("queueing pageflip failed: %m\n");
1042 if (output->pageflip_timer)
1043 wl_event_source_timer_update(output->pageflip_timer,
1044 backend->pageflip_timeout);
1046 output->fb_last = drm_fb_ref(output->fb_current);
1047 output->page_flip_pending = 1;
1052 /* if we cannot page-flip, immediately finish frame */
1053 weston_output_finish_frame(output_base, NULL,
1054 WP_PRESENTATION_FEEDBACK_INVALID);
1058 drm_output_update_msc(struct drm_output *output, unsigned int seq)
1060 uint64_t msc_hi = output->base.msc >> 32;
1062 if (seq < (output->base.msc & 0xffffffff))
1065 output->base.msc = (msc_hi << 32) + seq;
1069 vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec,
1072 struct drm_plane *s = (struct drm_plane *)data;
1073 struct drm_output *output = s->output;
1075 uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
1076 WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
1078 drm_output_update_msc(output, frame);
1079 output->vblank_pending--;
1080 assert(output->vblank_pending >= 0);
1082 assert(s->fb_last || s->fb_current);
1083 drm_fb_unref(s->fb_last);
1086 if (!output->page_flip_pending && !output->vblank_pending) {
1087 /* Stop the pageflip timer instead of rearming it here */
1088 if (output->pageflip_timer)
1089 wl_event_source_timer_update(output->pageflip_timer, 0);
1092 ts.tv_nsec = usec * 1000;
1093 weston_output_finish_frame(&output->base, &ts, flags);
1098 drm_output_destroy(struct weston_output *base);
1101 page_flip_handler(int fd, unsigned int frame,
1102 unsigned int sec, unsigned int usec, void *data)
1104 struct drm_output *output = data;
1106 uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_VSYNC |
1107 WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
1108 WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
1110 drm_output_update_msc(output, frame);
1112 assert(output->page_flip_pending);
1113 output->page_flip_pending = 0;
1115 drm_fb_unref(output->fb_last);
1116 output->fb_last = NULL;
1118 if (output->destroy_pending)
1119 drm_output_destroy(&output->base);
1120 else if (output->disable_pending)
1121 weston_output_disable(&output->base);
1122 else if (!output->vblank_pending) {
1123 /* Stop the pageflip timer instead of rearming it here */
1124 if (output->pageflip_timer)
1125 wl_event_source_timer_update(output->pageflip_timer, 0);
1128 ts.tv_nsec = usec * 1000;
1129 weston_output_finish_frame(&output->base, &ts, flags);
1131 /* We can't call this from frame_notify, because the output's
1132 * repaint needed flag is cleared just after that */
1133 if (output->recorder)
1134 weston_output_schedule_repaint(&output->base);
1139 drm_output_check_plane_format(struct drm_plane *p,
1140 struct weston_view *ev, struct gbm_bo *bo)
1144 format = gbm_bo_get_format(bo);
1146 if (format == GBM_FORMAT_ARGB8888) {
1147 pixman_region32_t r;
1149 pixman_region32_init_rect(&r, 0, 0,
1151 ev->surface->height);
1152 pixman_region32_subtract(&r, &r, &ev->surface->opaque);
1154 if (!pixman_region32_not_empty(&r))
1155 format = GBM_FORMAT_XRGB8888;
1157 pixman_region32_fini(&r);
1160 for (i = 0; i < p->count_formats; i++)
1161 if (p->formats[i] == format)
1167 static struct weston_plane *
1168 drm_output_prepare_overlay_view(struct drm_output *output,
1169 struct weston_view *ev)
1171 struct weston_compositor *ec = output->base.compositor;
1172 struct drm_backend *b = to_drm_backend(ec);
1173 struct weston_buffer_viewport *viewport = &ev->surface->buffer_viewport;
1174 struct wl_resource *buffer_resource;
1175 struct drm_plane *p;
1176 struct linux_dmabuf_buffer *dmabuf;
1179 pixman_region32_t dest_rect, src_rect;
1180 pixman_box32_t *box, tbox;
1182 wl_fixed_t sx1, sy1, sx2, sy2;
1184 if (b->sprites_are_broken)
1187 /* Don't import buffers which span multiple outputs. */
1188 if (ev->output_mask != (1u << output->base.id))
1191 /* We can only import GBM buffers. */
1195 if (ev->surface->buffer_ref.buffer == NULL)
1197 buffer_resource = ev->surface->buffer_ref.buffer->resource;
1198 if (wl_shm_buffer_get(buffer_resource))
1201 if (viewport->buffer.transform != output->base.transform)
1203 if (viewport->buffer.scale != output->base.current_scale)
1205 if (!drm_view_transform_supported(ev))
1208 if (ev->alpha != 1.0f)
1211 wl_list_for_each(p, &b->sprite_list, link) {
1212 if (!drm_plane_crtc_supported(output, p))
1215 if (!p->fb_pending) {
1221 /* No sprites available */
1225 if ((dmabuf = linux_dmabuf_buffer_get(buffer_resource))) {
1226 #ifdef HAVE_GBM_FD_IMPORT
1229 * Use AddFB2 directly, do not go via GBM.
1230 * Add support for multiplanar formats.
1231 * Both require refactoring in the DRM-backend to
1232 * support a mix of gbm_bos and drmfbs.
1234 struct gbm_import_fd_data gbm_dmabuf = {
1235 .fd = dmabuf->attributes.fd[0],
1236 .width = dmabuf->attributes.width,
1237 .height = dmabuf->attributes.height,
1238 .stride = dmabuf->attributes.stride[0],
1239 .format = dmabuf->attributes.format
1244 * Currently the buffer is rejected if any dmabuf attribute
1245 * flag is set. This keeps us from passing an inverted /
1246 * interlaced / bottom-first buffer (or any other type that may
1247 * be added in the future) through to an overlay. Ultimately,
1248 * these types of buffers should be handled through buffer
1249 * transforms and not as spot-checks requiring specific
1251 if (dmabuf->attributes.n_planes != 1 ||
1252 dmabuf->attributes.offset[0] != 0 ||
1253 dmabuf->attributes.flags)
1256 bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_FD, &gbm_dmabuf,
1257 GBM_BO_USE_SCANOUT);
1262 bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER,
1263 buffer_resource, GBM_BO_USE_SCANOUT);
1268 format = drm_output_check_plane_format(p, ev, bo);
1274 p->fb_pending = drm_fb_get_from_bo(bo, b, format, BUFFER_CLIENT);
1275 if (!p->fb_pending) {
1280 drm_fb_set_buffer(p->fb_pending, ev->surface->buffer_ref.buffer);
1282 box = pixman_region32_extents(&ev->transform.boundingbox);
1283 p->base.x = box->x1;
1284 p->base.y = box->y1;
1287 * Calculate the source & dest rects properly based on actual
1288 * position (note the caller has called weston_view_update_transform()
1291 pixman_region32_init(&dest_rect);
1292 pixman_region32_intersect(&dest_rect, &ev->transform.boundingbox,
1293 &output->base.region);
1294 pixman_region32_translate(&dest_rect, -output->base.x, -output->base.y);
1295 box = pixman_region32_extents(&dest_rect);
1296 tbox = weston_transformed_rect(output->base.width,
1297 output->base.height,
1298 output->base.transform,
1299 output->base.current_scale,
1301 p->dest_x = tbox.x1;
1302 p->dest_y = tbox.y1;
1303 p->dest_w = tbox.x2 - tbox.x1;
1304 p->dest_h = tbox.y2 - tbox.y1;
1305 pixman_region32_fini(&dest_rect);
1307 pixman_region32_init(&src_rect);
1308 pixman_region32_intersect(&src_rect, &ev->transform.boundingbox,
1309 &output->base.region);
1310 box = pixman_region32_extents(&src_rect);
1312 weston_view_from_global_fixed(ev,
1313 wl_fixed_from_int(box->x1),
1314 wl_fixed_from_int(box->y1),
1316 weston_view_from_global_fixed(ev,
1317 wl_fixed_from_int(box->x2),
1318 wl_fixed_from_int(box->y2),
1325 if (sx2 > wl_fixed_from_int(ev->surface->width))
1326 sx2 = wl_fixed_from_int(ev->surface->width);
1327 if (sy2 > wl_fixed_from_int(ev->surface->height))
1328 sy2 = wl_fixed_from_int(ev->surface->height);
1335 tbox = weston_transformed_rect(wl_fixed_from_int(ev->surface->width),
1336 wl_fixed_from_int(ev->surface->height),
1337 viewport->buffer.transform,
1338 viewport->buffer.scale,
1341 p->src_x = tbox.x1 << 8;
1342 p->src_y = tbox.y1 << 8;
1343 p->src_w = (tbox.x2 - tbox.x1) << 8;
1344 p->src_h = (tbox.y2 - tbox.y1) << 8;
1345 pixman_region32_fini(&src_rect);
1350 static struct weston_plane *
1351 drm_output_prepare_cursor_view(struct drm_output *output,
1352 struct weston_view *ev)
1354 struct drm_backend *b = to_drm_backend(output->base.compositor);
1355 struct weston_buffer_viewport *viewport = &ev->surface->buffer_viewport;
1356 struct wl_shm_buffer *shmbuf;
1359 if (b->cursors_are_broken)
1362 if (output->cursor_view)
1365 /* Don't import buffers which span multiple outputs. */
1366 if (ev->output_mask != (1u << output->base.id))
1369 /* We use GBM to import SHM buffers. */
1373 if (ev->surface->buffer_ref.buffer == NULL)
1375 shmbuf = wl_shm_buffer_get(ev->surface->buffer_ref.buffer->resource);
1378 if (wl_shm_buffer_get_format(shmbuf) != WL_SHM_FORMAT_ARGB8888)
1381 if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL)
1383 if (ev->transform.enabled &&
1384 (ev->transform.matrix.type > WESTON_MATRIX_TRANSFORM_TRANSLATE))
1386 if (viewport->buffer.scale != output->base.current_scale)
1388 if (ev->geometry.scissor_enabled)
1391 if (ev->surface->width > b->cursor_width ||
1392 ev->surface->height > b->cursor_height)
1395 output->cursor_view = ev;
1396 weston_view_to_global_float(ev, 0, 0, &x, &y);
1397 output->cursor_plane.x = x;
1398 output->cursor_plane.y = y;
1400 return &output->cursor_plane;
1404 * Update the image for the current cursor surface
1406 * @param b DRM backend structure
1407 * @param bo GBM buffer object to write into
1408 * @param ev View to use for cursor image
1411 cursor_bo_update(struct drm_backend *b, struct gbm_bo *bo,
1412 struct weston_view *ev)
1414 struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
1415 uint32_t buf[b->cursor_width * b->cursor_height];
1420 assert(buffer && buffer->shm_buffer);
1421 assert(buffer->shm_buffer == wl_shm_buffer_get(buffer->resource));
1422 assert(ev->surface->width <= b->cursor_width);
1423 assert(ev->surface->height <= b->cursor_height);
1425 memset(buf, 0, sizeof buf);
1426 stride = wl_shm_buffer_get_stride(buffer->shm_buffer);
1427 s = wl_shm_buffer_get_data(buffer->shm_buffer);
1429 wl_shm_buffer_begin_access(buffer->shm_buffer);
1430 for (i = 0; i < ev->surface->height; i++)
1431 memcpy(buf + i * b->cursor_width,
1433 ev->surface->width * 4);
1434 wl_shm_buffer_end_access(buffer->shm_buffer);
1436 if (gbm_bo_write(bo, buf, sizeof buf) < 0)
1437 weston_log("failed update cursor: %m\n");
1441 drm_output_set_cursor(struct drm_output *output)
1443 struct weston_view *ev = output->cursor_view;
1444 struct drm_backend *b = to_drm_backend(output->base.compositor);
1450 drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
1454 if (pixman_region32_not_empty(&output->cursor_plane.damage)) {
1455 pixman_region32_fini(&output->cursor_plane.damage);
1456 pixman_region32_init(&output->cursor_plane.damage);
1457 output->current_cursor ^= 1;
1458 bo = output->gbm_cursor_fb[output->current_cursor]->bo;
1460 cursor_bo_update(b, bo, ev);
1461 handle = gbm_bo_get_handle(bo).s32;
1462 if (drmModeSetCursor(b->drm.fd, output->crtc_id, handle,
1463 b->cursor_width, b->cursor_height)) {
1464 weston_log("failed to set cursor: %m\n");
1465 b->cursors_are_broken = 1;
1469 x = (output->cursor_plane.x - output->base.x) *
1470 output->base.current_scale;
1471 y = (output->cursor_plane.y - output->base.y) *
1472 output->base.current_scale;
1474 if (drmModeMoveCursor(b->drm.fd, output->crtc_id, x, y)) {
1475 weston_log("failed to move cursor: %m\n");
1476 b->cursors_are_broken = 1;
1481 drm_assign_planes(struct weston_output *output_base, void *repaint_data)
1483 struct drm_backend *b = to_drm_backend(output_base->compositor);
1484 struct drm_output *output = to_drm_output(output_base);
1485 struct weston_view *ev, *next;
1486 pixman_region32_t overlap, surface_overlap;
1487 struct weston_plane *primary, *next_plane;
1490 * Find a surface for each sprite in the output using some heuristics:
1492 * 2) frequency of update
1493 * 3) opacity (though some hw might support alpha blending)
1494 * 4) clipping (this can be fixed with color keys)
1496 * The idea is to save on blitting since this should save power.
1497 * If we can get a large video surface on the sprite for example,
1498 * the main display surface may not need to update at all, and
1499 * the client buffer can be used directly for the sprite surface
1500 * as we do for flipping full screen surfaces.
1502 pixman_region32_init(&overlap);
1503 primary = &output_base->compositor->primary_plane;
1505 output->cursor_view = NULL;
1506 output->cursor_plane.x = INT32_MIN;
1507 output->cursor_plane.y = INT32_MIN;
1509 wl_list_for_each_safe(ev, next, &output_base->compositor->view_list, link) {
1510 struct weston_surface *es = ev->surface;
1512 /* Test whether this buffer can ever go into a plane:
1513 * non-shm, or small enough to be a cursor.
1515 * Also, keep a reference when using the pixman renderer.
1516 * That makes it possible to do a seamless switch to the GL
1517 * renderer and since the pixman renderer keeps a reference
1518 * to the buffer anyway, there is no side effects.
1520 if (b->use_pixman ||
1521 (es->buffer_ref.buffer &&
1522 (!wl_shm_buffer_get(es->buffer_ref.buffer->resource) ||
1523 (ev->surface->width <= b->cursor_width &&
1524 ev->surface->height <= b->cursor_height))))
1525 es->keep_buffer = true;
1527 es->keep_buffer = false;
1529 pixman_region32_init(&surface_overlap);
1530 pixman_region32_intersect(&surface_overlap, &overlap,
1531 &ev->transform.boundingbox);
1534 if (pixman_region32_not_empty(&surface_overlap))
1535 next_plane = primary;
1536 if (next_plane == NULL)
1537 next_plane = drm_output_prepare_cursor_view(output, ev);
1538 if (next_plane == NULL)
1539 next_plane = drm_output_prepare_scanout_view(output, ev);
1540 if (next_plane == NULL)
1541 next_plane = drm_output_prepare_overlay_view(output, ev);
1542 if (next_plane == NULL)
1543 next_plane = primary;
1545 weston_view_move_to_plane(ev, next_plane);
1547 if (next_plane == primary)
1548 pixman_region32_union(&overlap, &overlap,
1549 &ev->transform.boundingbox);
1551 if (next_plane == primary ||
1552 next_plane == &output->cursor_plane) {
1553 /* cursor plane involves a copy */
1556 /* All other planes are a direct scanout of a
1557 * single client buffer.
1559 ev->psf_flags = WP_PRESENTATION_FEEDBACK_KIND_ZERO_COPY;
1562 pixman_region32_fini(&surface_overlap);
1564 pixman_region32_fini(&overlap);
1568 * Find the closest-matching mode for a given target
1570 * Given a target mode, find the most suitable mode amongst the output's
1571 * current mode list to use, preferring the current mode if possible, to
1572 * avoid an expensive mode switch.
1574 * @param output DRM output
1575 * @param target_mode Mode to attempt to match
1576 * @returns Pointer to a mode from the output's mode list
1578 static struct drm_mode *
1579 choose_mode (struct drm_output *output, struct weston_mode *target_mode)
1581 struct drm_mode *tmp_mode = NULL, *mode;
1583 if (output->base.current_mode->width == target_mode->width &&
1584 output->base.current_mode->height == target_mode->height &&
1585 (output->base.current_mode->refresh == target_mode->refresh ||
1586 target_mode->refresh == 0))
1587 return (struct drm_mode *)output->base.current_mode;
1589 wl_list_for_each(mode, &output->base.mode_list, base.link) {
1590 if (mode->mode_info.hdisplay == target_mode->width &&
1591 mode->mode_info.vdisplay == target_mode->height) {
1592 if (mode->base.refresh == target_mode->refresh ||
1593 target_mode->refresh == 0) {
1595 } else if (!tmp_mode)
1604 drm_output_init_egl(struct drm_output *output, struct drm_backend *b);
1606 drm_output_fini_egl(struct drm_output *output);
1608 drm_output_init_pixman(struct drm_output *output, struct drm_backend *b);
1610 drm_output_fini_pixman(struct drm_output *output);
1613 drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mode)
1615 struct drm_output *output;
1616 struct drm_mode *drm_mode;
1617 struct drm_backend *b;
1619 if (output_base == NULL) {
1620 weston_log("output is NULL.\n");
1625 weston_log("mode is NULL.\n");
1629 b = to_drm_backend(output_base->compositor);
1630 output = to_drm_output(output_base);
1631 drm_mode = choose_mode (output, mode);
1634 weston_log("%s, invalid resolution:%dx%d\n", __func__, mode->width, mode->height);
1638 if (&drm_mode->base == output->base.current_mode)
1641 output->base.current_mode->flags = 0;
1643 output->base.current_mode = &drm_mode->base;
1644 output->base.current_mode->flags =
1645 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
1647 /* XXX: This drops our current buffer too early, before we've started
1648 * displaying it. Ideally this should be much more atomic and
1649 * integrated with a full repaint cycle, rather than doing a
1650 * sledgehammer modeswitch first, and only later showing new
1653 drm_fb_unref(output->fb_current);
1654 assert(!output->fb_last);
1655 assert(!output->fb_pending);
1656 output->fb_last = output->fb_current = NULL;
1658 if (b->use_pixman) {
1659 drm_output_fini_pixman(output);
1660 if (drm_output_init_pixman(output, b) < 0) {
1661 weston_log("failed to init output pixman state with "
1666 drm_output_fini_egl(output);
1667 if (drm_output_init_egl(output, b) < 0) {
1668 weston_log("failed to init output egl state with "
1678 on_drm_input(int fd, uint32_t mask, void *data)
1680 drmEventContext evctx;
1682 memset(&evctx, 0, sizeof evctx);
1684 evctx.page_flip_handler = page_flip_handler;
1685 evctx.vblank_handler = vblank_handler;
1686 drmHandleEvent(fd, &evctx);
1692 init_kms_caps(struct drm_backend *b)
1698 weston_log("using %s\n", b->drm.filename);
1700 ret = drmGetCap(b->drm.fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap);
1701 if (ret == 0 && cap == 1)
1702 clk_id = CLOCK_MONOTONIC;
1704 clk_id = CLOCK_REALTIME;
1706 if (weston_compositor_set_presentation_clock(b->compositor, clk_id) < 0) {
1707 weston_log("Error: failed to set presentation clock %d.\n",
1712 ret = drmGetCap(b->drm.fd, DRM_CAP_CURSOR_WIDTH, &cap);
1714 b->cursor_width = cap;
1716 b->cursor_width = 64;
1718 ret = drmGetCap(b->drm.fd, DRM_CAP_CURSOR_HEIGHT, &cap);
1720 b->cursor_height = cap;
1722 b->cursor_height = 64;
1727 static struct gbm_device *
1728 create_gbm_device(int fd)
1730 struct gbm_device *gbm;
1732 gl_renderer = weston_load_module("gl-renderer.so",
1733 "gl_renderer_interface");
1737 /* GBM will load a dri driver, but even though they need symbols from
1738 * libglapi, in some version of Mesa they are not linked to it. Since
1739 * only the gl-renderer module links to it, the call above won't make
1740 * these symbols globally available, and loading the DRI driver fails.
1741 * Workaround this by dlopen()'ing libglapi with RTLD_GLOBAL. */
1742 dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL);
1744 gbm = gbm_create_device(fd);
1749 /* When initializing EGL, if the preferred buffer format isn't available
1750 * we may be able to substitute an ARGB format for an XRGB one.
1752 * This returns 0 if substitution isn't possible, but 0 might be a
1753 * legitimate format for other EGL platforms, so the caller is
1754 * responsible for checking for 0 before calling gl_renderer->create().
1756 * This works around https://bugs.freedesktop.org/show_bug.cgi?id=89689
1757 * but it's entirely possible we'll see this again on other implementations.
1760 fallback_format_for(uint32_t format)
1763 case GBM_FORMAT_XRGB8888:
1764 return GBM_FORMAT_ARGB8888;
1765 case GBM_FORMAT_XRGB2101010:
1766 return GBM_FORMAT_ARGB2101010;
1773 drm_backend_create_gl_renderer(struct drm_backend *b)
1775 EGLint format[3] = {
1777 fallback_format_for(b->gbm_format),
1784 if (gl_renderer->display_create(b->compositor,
1785 EGL_PLATFORM_GBM_KHR,
1788 gl_renderer->opaque_attribs,
1798 init_egl(struct drm_backend *b)
1800 b->gbm = create_gbm_device(b->drm.fd);
1805 if (drm_backend_create_gl_renderer(b) < 0) {
1806 gbm_device_destroy(b->gbm);
1814 init_pixman(struct drm_backend *b)
1816 return pixman_renderer_init(b->compositor);
1820 * Add a mode to output's mode list
1822 * Copy the supplied DRM mode into a Weston mode structure, and add it to the
1823 * output's mode list.
1825 * @param output DRM output to add mode to
1826 * @param info DRM mode structure to add
1827 * @returns Newly-allocated Weston/DRM mode structure
1829 static struct drm_mode *
1830 drm_output_add_mode(struct drm_output *output, const drmModeModeInfo *info)
1832 struct drm_mode *mode;
1835 mode = malloc(sizeof *mode);
1839 mode->base.flags = 0;
1840 mode->base.width = info->hdisplay;
1841 mode->base.height = info->vdisplay;
1843 /* Calculate higher precision (mHz) refresh rate */
1844 refresh = (info->clock * 1000000LL / info->htotal +
1845 info->vtotal / 2) / info->vtotal;
1847 if (info->flags & DRM_MODE_FLAG_INTERLACE)
1849 if (info->flags & DRM_MODE_FLAG_DBLSCAN)
1851 if (info->vscan > 1)
1852 refresh /= info->vscan;
1854 mode->base.refresh = refresh;
1855 mode->mode_info = *info;
1857 if (info->type & DRM_MODE_TYPE_PREFERRED)
1858 mode->base.flags |= WL_OUTPUT_MODE_PREFERRED;
1860 wl_list_insert(output->base.mode_list.prev, &mode->base.link);
1866 drm_subpixel_to_wayland(int drm_value)
1868 switch (drm_value) {
1870 case DRM_MODE_SUBPIXEL_UNKNOWN:
1871 return WL_OUTPUT_SUBPIXEL_UNKNOWN;
1872 case DRM_MODE_SUBPIXEL_NONE:
1873 return WL_OUTPUT_SUBPIXEL_NONE;
1874 case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
1875 return WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB;
1876 case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
1877 return WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR;
1878 case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
1879 return WL_OUTPUT_SUBPIXEL_VERTICAL_RGB;
1880 case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
1881 return WL_OUTPUT_SUBPIXEL_VERTICAL_BGR;
1885 /* returns a value between 0-255 range, where higher is brighter */
1887 drm_get_backlight(struct drm_output *output)
1889 long brightness, max_brightness, norm;
1891 brightness = backlight_get_brightness(output->backlight);
1892 max_brightness = backlight_get_max_brightness(output->backlight);
1894 /* convert it on a scale of 0 to 255 */
1895 norm = (brightness * 255)/(max_brightness);
1897 return (uint32_t) norm;
1900 /* values accepted are between 0-255 range */
1902 drm_set_backlight(struct weston_output *output_base, uint32_t value)
1904 struct drm_output *output = to_drm_output(output_base);
1905 long max_brightness, new_brightness;
1907 if (!output->backlight)
1913 max_brightness = backlight_get_max_brightness(output->backlight);
1915 /* get denormalized value */
1916 new_brightness = (value * max_brightness) / 255;
1918 backlight_set_brightness(output->backlight, new_brightness);
1921 static drmModePropertyPtr
1922 drm_get_prop(int fd, drmModeConnectorPtr connector, const char *name)
1924 drmModePropertyPtr props;
1927 for (i = 0; i < connector->count_props; i++) {
1928 props = drmModeGetProperty(fd, connector->props[i]);
1932 if (!strcmp(props->name, name))
1935 drmModeFreeProperty(props);
1942 drm_set_dpms(struct weston_output *output_base, enum dpms_enum level)
1944 struct drm_output *output = to_drm_output(output_base);
1945 struct weston_compositor *ec = output_base->compositor;
1946 struct drm_backend *b = to_drm_backend(ec);
1949 if (!output->dpms_prop)
1952 ret = drmModeConnectorSetProperty(b->drm.fd, output->connector_id,
1953 output->dpms_prop->prop_id, level);
1955 weston_log("DRM: DPMS: failed property set for %s\n",
1960 output->dpms = level;
1963 static const char * const connector_type_names[] = {
1964 [DRM_MODE_CONNECTOR_Unknown] = "Unknown",
1965 [DRM_MODE_CONNECTOR_VGA] = "VGA",
1966 [DRM_MODE_CONNECTOR_DVII] = "DVI-I",
1967 [DRM_MODE_CONNECTOR_DVID] = "DVI-D",
1968 [DRM_MODE_CONNECTOR_DVIA] = "DVI-A",
1969 [DRM_MODE_CONNECTOR_Composite] = "Composite",
1970 [DRM_MODE_CONNECTOR_SVIDEO] = "SVIDEO",
1971 [DRM_MODE_CONNECTOR_LVDS] = "LVDS",
1972 [DRM_MODE_CONNECTOR_Component] = "Component",
1973 [DRM_MODE_CONNECTOR_9PinDIN] = "DIN",
1974 [DRM_MODE_CONNECTOR_DisplayPort] = "DP",
1975 [DRM_MODE_CONNECTOR_HDMIA] = "HDMI-A",
1976 [DRM_MODE_CONNECTOR_HDMIB] = "HDMI-B",
1977 [DRM_MODE_CONNECTOR_TV] = "TV",
1978 [DRM_MODE_CONNECTOR_eDP] = "eDP",
1979 #ifdef DRM_MODE_CONNECTOR_DSI
1980 [DRM_MODE_CONNECTOR_VIRTUAL] = "Virtual",
1981 [DRM_MODE_CONNECTOR_DSI] = "DSI",
1986 make_connector_name(const drmModeConnector *con)
1989 const char *type_name = NULL;
1991 if (con->connector_type < ARRAY_LENGTH(connector_type_names))
1992 type_name = connector_type_names[con->connector_type];
1995 type_name = "UNNAMED";
1997 snprintf(name, sizeof name, "%s-%d", type_name, con->connector_type_id);
1999 return strdup(name);
2003 find_crtc_for_connector(struct drm_backend *b,
2004 drmModeRes *resources, drmModeConnector *connector)
2006 drmModeEncoder *encoder;
2010 for (j = 0; j < connector->count_encoders; j++) {
2011 uint32_t possible_crtcs, encoder_id, crtc_id;
2013 encoder = drmModeGetEncoder(b->drm.fd, connector->encoders[j]);
2014 if (encoder == NULL) {
2015 weston_log("Failed to get encoder.\n");
2018 encoder_id = encoder->encoder_id;
2019 possible_crtcs = encoder->possible_crtcs;
2020 crtc_id = encoder->crtc_id;
2021 drmModeFreeEncoder(encoder);
2023 for (i = 0; i < resources->count_crtcs; i++) {
2024 if (!(possible_crtcs & (1 << i)))
2027 if (drm_output_find_by_crtc(b, resources->crtcs[i]))
2030 /* Try to preserve the existing
2031 * CRTC -> encoder -> connector routing; it makes
2032 * initialisation faster, and also since we have a
2033 * very dumb picking algorithm, may preserve a better
2035 if (!connector->encoder_id ||
2036 (encoder_id == connector->encoder_id &&
2037 crtc_id == resources->crtcs[i]))
2047 static void drm_output_fini_cursor_egl(struct drm_output *output)
2051 for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
2052 drm_fb_unref(output->gbm_cursor_fb[i]);
2053 output->gbm_cursor_fb[i] = NULL;
2058 drm_output_init_cursor_egl(struct drm_output *output, struct drm_backend *b)
2062 for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
2065 bo = gbm_bo_create(b->gbm, b->cursor_width, b->cursor_height,
2066 GBM_FORMAT_ARGB8888,
2067 GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
2071 output->gbm_cursor_fb[i] =
2072 drm_fb_get_from_bo(bo, b, GBM_FORMAT_ARGB8888,
2074 if (!output->gbm_cursor_fb[i]) {
2083 weston_log("cursor buffers unavailable, using gl cursors\n");
2084 b->cursors_are_broken = 1;
2085 drm_output_fini_cursor_egl(output);
2089 /* Init output state that depends on gl or gbm */
2091 drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
2093 EGLint format[2] = {
2095 fallback_format_for(output->gbm_format),
2099 output->gbm_surface = gbm_surface_create(b->gbm,
2100 output->base.current_mode->width,
2101 output->base.current_mode->height,
2103 GBM_BO_USE_SCANOUT |
2104 GBM_BO_USE_RENDERING);
2105 if (!output->gbm_surface) {
2106 weston_log("failed to create gbm surface\n");
2112 if (gl_renderer->output_window_create(&output->base,
2113 (EGLNativeWindowType)output->gbm_surface,
2114 output->gbm_surface,
2115 gl_renderer->opaque_attribs,
2118 weston_log("failed to create gl renderer output state\n");
2119 gbm_surface_destroy(output->gbm_surface);
2123 drm_output_init_cursor_egl(output, b);
2129 drm_output_fini_egl(struct drm_output *output)
2131 gl_renderer->output_destroy(&output->base);
2132 gbm_surface_destroy(output->gbm_surface);
2133 drm_output_fini_cursor_egl(output);
2137 drm_output_init_pixman(struct drm_output *output, struct drm_backend *b)
2139 int w = output->base.current_mode->width;
2140 int h = output->base.current_mode->height;
2141 uint32_t format = output->gbm_format;
2142 uint32_t pixman_format;
2146 case GBM_FORMAT_XRGB8888:
2147 pixman_format = PIXMAN_x8r8g8b8;
2149 case GBM_FORMAT_RGB565:
2150 pixman_format = PIXMAN_r5g6b5;
2153 weston_log("Unsupported pixman format 0x%x\n", format);
2157 /* FIXME error checking */
2158 for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
2159 output->dumb[i] = drm_fb_create_dumb(b, w, h, format);
2160 if (!output->dumb[i])
2164 pixman_image_create_bits(pixman_format, w, h,
2165 output->dumb[i]->map,
2166 output->dumb[i]->stride);
2167 if (!output->image[i])
2171 if (pixman_renderer_output_create(&output->base) < 0)
2174 pixman_region32_init_rect(&output->previous_damage,
2175 output->base.x, output->base.y, output->base.width, output->base.height);
2180 for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
2181 if (output->dumb[i])
2182 drm_fb_unref(output->dumb[i]);
2183 if (output->image[i])
2184 pixman_image_unref(output->image[i]);
2186 output->dumb[i] = NULL;
2187 output->image[i] = NULL;
2194 drm_output_fini_pixman(struct drm_output *output)
2198 pixman_renderer_output_destroy(&output->base);
2199 pixman_region32_fini(&output->previous_damage);
2201 for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
2202 pixman_image_unref(output->image[i]);
2203 drm_fb_unref(output->dumb[i]);
2204 output->dumb[i] = NULL;
2205 output->image[i] = NULL;
2210 edid_parse_string(const uint8_t *data, char text[])
2215 /* this is always 12 bytes, but we can't guarantee it's null
2216 * terminated or not junk. */
2217 strncpy(text, (const char *) data, 12);
2219 /* guarantee our new string is null-terminated */
2222 /* remove insane chars */
2223 for (i = 0; text[i] != '\0'; i++) {
2224 if (text[i] == '\n' ||
2231 /* ensure string is printable */
2232 for (i = 0; text[i] != '\0'; i++) {
2233 if (!isprint(text[i])) {
2239 /* if the string is random junk, ignore the string */
2244 #define EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING 0xfe
2245 #define EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME 0xfc
2246 #define EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER 0xff
2247 #define EDID_OFFSET_DATA_BLOCKS 0x36
2248 #define EDID_OFFSET_LAST_BLOCK 0x6c
2249 #define EDID_OFFSET_PNPID 0x08
2250 #define EDID_OFFSET_SERIAL 0x0c
2253 edid_parse(struct drm_edid *edid, const uint8_t *data, size_t length)
2256 uint32_t serial_number;
2261 if (data[0] != 0x00 || data[1] != 0xff)
2264 /* decode the PNP ID from three 5 bit words packed into 2 bytes
2269 edid->pnp_id[0] = 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x7c) / 4) - 1;
2270 edid->pnp_id[1] = 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x3) * 8) + ((data[EDID_OFFSET_PNPID + 1] & 0xe0) / 32) - 1;
2271 edid->pnp_id[2] = 'A' + (data[EDID_OFFSET_PNPID + 1] & 0x1f) - 1;
2272 edid->pnp_id[3] = '\0';
2274 /* maybe there isn't a ASCII serial number descriptor, so use this instead */
2275 serial_number = (uint32_t) data[EDID_OFFSET_SERIAL + 0];
2276 serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 1] * 0x100;
2277 serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 2] * 0x10000;
2278 serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 3] * 0x1000000;
2279 if (serial_number > 0)
2280 sprintf(edid->serial_number, "%lu", (unsigned long) serial_number);
2282 /* parse EDID data */
2283 for (i = EDID_OFFSET_DATA_BLOCKS;
2284 i <= EDID_OFFSET_LAST_BLOCK;
2286 /* ignore pixel clock data */
2292 /* any useful blocks? */
2293 if (data[i+3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME) {
2294 edid_parse_string(&data[i+5],
2295 edid->monitor_name);
2296 } else if (data[i+3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER) {
2297 edid_parse_string(&data[i+5],
2298 edid->serial_number);
2299 } else if (data[i+3] == EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING) {
2300 edid_parse_string(&data[i+5],
2308 find_and_parse_output_edid(struct drm_backend *b,
2309 struct drm_output *output,
2310 drmModeConnector *connector)
2312 drmModePropertyBlobPtr edid_blob = NULL;
2313 drmModePropertyPtr property;
2317 for (i = 0; i < connector->count_props && !edid_blob; i++) {
2318 property = drmModeGetProperty(b->drm.fd, connector->props[i]);
2321 if ((property->flags & DRM_MODE_PROP_BLOB) &&
2322 !strcmp(property->name, "EDID")) {
2323 edid_blob = drmModeGetPropertyBlob(b->drm.fd,
2324 connector->prop_values[i]);
2326 drmModeFreeProperty(property);
2331 rc = edid_parse(&output->edid,
2335 weston_log("EDID data '%s', '%s', '%s'\n",
2336 output->edid.pnp_id,
2337 output->edid.monitor_name,
2338 output->edid.serial_number);
2339 if (output->edid.pnp_id[0] != '\0')
2340 output->base.make = output->edid.pnp_id;
2341 if (output->edid.monitor_name[0] != '\0')
2342 output->base.model = output->edid.monitor_name;
2343 if (output->edid.serial_number[0] != '\0')
2344 output->base.serial_number = output->edid.serial_number;
2346 drmModeFreePropertyBlob(edid_blob);
2352 parse_modeline(const char *s, drmModeModeInfo *mode)
2358 mode->type = DRM_MODE_TYPE_USERDEF;
2364 if (sscanf(s, "%f %hd %hd %hd %hd %hd %hd %hd %hd %15s %15s",
2373 &mode->vtotal, hsync, vsync) != 11)
2376 mode->clock = fclock * 1000;
2377 if (strcmp(hsync, "+hsync") == 0)
2378 mode->flags |= DRM_MODE_FLAG_PHSYNC;
2379 else if (strcmp(hsync, "-hsync") == 0)
2380 mode->flags |= DRM_MODE_FLAG_NHSYNC;
2384 if (strcmp(vsync, "+vsync") == 0)
2385 mode->flags |= DRM_MODE_FLAG_PVSYNC;
2386 else if (strcmp(vsync, "-vsync") == 0)
2387 mode->flags |= DRM_MODE_FLAG_NVSYNC;
2391 snprintf(mode->name, sizeof mode->name, "%dx%d@%.3f",
2392 mode->hdisplay, mode->vdisplay, fclock);
2398 setup_output_seat_constraint(struct drm_backend *b,
2399 struct weston_output *output,
2402 if (strcmp(s, "") != 0) {
2403 struct weston_pointer *pointer;
2404 struct udev_seat *seat;
2406 seat = udev_seat_get_named(&b->input, s);
2410 seat->base.output = output;
2412 pointer = weston_seat_get_pointer(&seat->base);
2414 weston_pointer_clamp(pointer,
2421 parse_gbm_format(const char *s, uint32_t default_value, uint32_t *gbm_format)
2426 *gbm_format = default_value;
2427 else if (strcmp(s, "xrgb8888") == 0)
2428 *gbm_format = GBM_FORMAT_XRGB8888;
2429 else if (strcmp(s, "rgb565") == 0)
2430 *gbm_format = GBM_FORMAT_RGB565;
2431 else if (strcmp(s, "xrgb2101010") == 0)
2432 *gbm_format = GBM_FORMAT_XRGB2101010;
2434 weston_log("fatal: unrecognized pixel format: %s\n", s);
2442 * Choose suitable mode for an output
2444 * Find the most suitable mode to use for initial setup (or reconfiguration on
2445 * hotplug etc) for a DRM output.
2447 * @param output DRM output to choose mode for
2448 * @param kind Strategy and preference to use when choosing mode
2449 * @param width Desired width for this output
2450 * @param height Desired height for this output
2451 * @param current_mode Mode currently being displayed on this output
2452 * @param modeline Manually-entered mode (may be NULL)
2453 * @returns A mode from the output's mode list, or NULL if none available
2455 static struct drm_mode *
2456 drm_output_choose_initial_mode(struct drm_backend *backend,
2457 struct drm_output *output,
2458 enum weston_drm_backend_output_mode mode,
2459 const char *modeline,
2460 const drmModeModeInfo *current_mode)
2462 struct drm_mode *preferred = NULL;
2463 struct drm_mode *current = NULL;
2464 struct drm_mode *configured = NULL;
2465 struct drm_mode *best = NULL;
2466 struct drm_mode *drm_mode;
2467 drmModeModeInfo drm_modeline;
2470 uint32_t refresh = 0;
2473 if (mode == WESTON_DRM_BACKEND_OUTPUT_PREFERRED && modeline) {
2474 n = sscanf(modeline, "%dx%d@%d", &width, &height, &refresh);
2475 if (n != 2 && n != 3) {
2478 if (parse_modeline(modeline, &drm_modeline) == 0) {
2479 configured = drm_output_add_mode(output, &drm_modeline);
2483 weston_log("Invalid modeline \"%s\" for output %s\n",
2484 modeline, output->base.name);
2489 wl_list_for_each_reverse(drm_mode, &output->base.mode_list, base.link) {
2490 if (width == drm_mode->base.width &&
2491 height == drm_mode->base.height &&
2492 (refresh == 0 || refresh == drm_mode->mode_info.vrefresh))
2493 configured = drm_mode;
2495 if (memcmp(current_mode, &drm_mode->mode_info,
2496 sizeof *current_mode) == 0)
2499 if (drm_mode->base.flags & WL_OUTPUT_MODE_PREFERRED)
2500 preferred = drm_mode;
2505 if (current == NULL && current_mode->clock != 0) {
2506 current = drm_output_add_mode(output, current_mode);
2511 if (mode == WESTON_DRM_BACKEND_OUTPUT_CURRENT)
2512 configured = current;
2526 weston_log("no available modes for %s\n", output->base.name);
2531 connector_get_current_mode(drmModeConnector *connector, int drm_fd,
2532 drmModeModeInfo *mode)
2534 drmModeEncoder *encoder;
2537 /* Get the current mode on the crtc that's currently driving
2538 * this connector. */
2539 encoder = drmModeGetEncoder(drm_fd, connector->encoder_id);
2540 memset(mode, 0, sizeof *mode);
2541 if (encoder != NULL) {
2542 crtc = drmModeGetCrtc(drm_fd, encoder->crtc_id);
2543 drmModeFreeEncoder(encoder);
2546 if (crtc->mode_valid)
2548 drmModeFreeCrtc(crtc);
2555 drm_output_set_mode(struct weston_output *base,
2556 enum weston_drm_backend_output_mode mode,
2557 const char *modeline)
2559 struct drm_output *output = to_drm_output(base);
2560 struct drm_backend *b = to_drm_backend(base->compositor);
2562 struct drm_mode *current;
2563 drmModeModeInfo crtc_mode;
2565 output->base.make = "unknown";
2566 output->base.model = "unknown";
2567 output->base.serial_number = "unknown";
2569 if (connector_get_current_mode(output->connector, b->drm.fd, &crtc_mode) < 0)
2572 current = drm_output_choose_initial_mode(b, output, mode, modeline, &crtc_mode);
2576 output->base.current_mode = ¤t->base;
2577 output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
2579 /* Set native_ fields, so weston_output_mode_switch_to_native() works */
2580 output->base.native_mode = output->base.current_mode;
2581 output->base.native_scale = output->base.current_scale;
2583 output->base.mm_width = output->connector->mmWidth;
2584 output->base.mm_height = output->connector->mmHeight;
2590 drm_output_set_gbm_format(struct weston_output *base,
2591 const char *gbm_format)
2593 struct drm_output *output = to_drm_output(base);
2594 struct drm_backend *b = to_drm_backend(base->compositor);
2596 if (parse_gbm_format(gbm_format, b->gbm_format, &output->gbm_format) == -1)
2597 output->gbm_format = b->gbm_format;
2601 drm_output_set_seat(struct weston_output *base,
2604 struct drm_output *output = to_drm_output(base);
2605 struct drm_backend *b = to_drm_backend(base->compositor);
2607 setup_output_seat_constraint(b, &output->base,
2612 drm_output_enable(struct weston_output *base)
2614 struct drm_output *output = to_drm_output(base);
2615 struct drm_backend *b = to_drm_backend(base->compositor);
2616 struct weston_mode *m;
2618 output->dpms_prop = drm_get_prop(b->drm.fd, output->connector, "DPMS");
2620 if (b->pageflip_timeout)
2621 drm_output_pageflip_timer_create(output);
2623 if (b->use_pixman) {
2624 if (drm_output_init_pixman(output, b) < 0) {
2625 weston_log("Failed to init output pixman state\n");
2628 } else if (drm_output_init_egl(output, b) < 0) {
2629 weston_log("Failed to init output gl state\n");
2633 if (output->backlight) {
2634 weston_log("Initialized backlight, device %s\n",
2635 output->backlight->path);
2636 output->base.set_backlight = drm_set_backlight;
2637 output->base.backlight_current = drm_get_backlight(output);
2639 weston_log("Failed to initialize backlight\n");
2642 output->base.start_repaint_loop = drm_output_start_repaint_loop;
2643 output->base.repaint = drm_output_repaint;
2644 output->base.assign_planes = drm_assign_planes;
2645 output->base.set_dpms = drm_set_dpms;
2646 output->base.switch_mode = drm_output_switch_mode;
2648 output->base.gamma_size = output->original_crtc->gamma_size;
2649 output->base.set_gamma = drm_output_set_gamma;
2651 output->base.subpixel = drm_subpixel_to_wayland(output->connector->subpixel);
2653 find_and_parse_output_edid(b, output, output->connector);
2654 if (output->connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
2655 output->connector->connector_type == DRM_MODE_CONNECTOR_eDP)
2656 output->base.connection_internal = true;
2658 weston_plane_init(&output->cursor_plane, b->compositor,
2659 INT32_MIN, INT32_MIN);
2660 weston_plane_init(&output->fb_plane, b->compositor, 0, 0);
2662 weston_compositor_stack_plane(b->compositor, &output->cursor_plane, NULL);
2663 weston_compositor_stack_plane(b->compositor, &output->fb_plane,
2664 &b->compositor->primary_plane);
2666 weston_log("Output %s, (connector %d, crtc %d)\n",
2667 output->base.name, output->connector_id, output->crtc_id);
2668 wl_list_for_each(m, &output->base.mode_list, link)
2669 weston_log_continue(STAMP_SPACE "mode %dx%d@%.1f%s%s%s\n",
2670 m->width, m->height, m->refresh / 1000.0,
2671 m->flags & WL_OUTPUT_MODE_PREFERRED ?
2673 m->flags & WL_OUTPUT_MODE_CURRENT ?
2675 output->connector->count_modes == 0 ?
2681 drmModeFreeProperty(output->dpms_prop);
2687 drm_output_deinit(struct weston_output *base)
2689 struct drm_output *output = to_drm_output(base);
2690 struct drm_backend *b = to_drm_backend(base->compositor);
2692 /* output->fb_last and output->fb_pending must not be set here;
2693 * destroy_pending/disable_pending exist to guarantee exactly this. */
2694 assert(!output->fb_last);
2695 assert(!output->fb_pending);
2696 drm_fb_unref(output->fb_current);
2697 output->fb_current = NULL;
2700 drm_output_fini_pixman(output);
2702 drm_output_fini_egl(output);
2704 weston_plane_release(&output->fb_plane);
2705 weston_plane_release(&output->cursor_plane);
2707 drmModeFreeProperty(output->dpms_prop);
2709 /* Turn off hardware cursor */
2710 drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
2714 drm_output_destroy(struct weston_output *base)
2716 struct drm_output *output = to_drm_output(base);
2717 struct drm_backend *b = to_drm_backend(base->compositor);
2718 struct drm_mode *drm_mode, *next;
2719 drmModeCrtcPtr origcrtc = output->original_crtc;
2721 if (output->page_flip_pending) {
2722 output->destroy_pending = 1;
2723 weston_log("destroy output while page flip pending\n");
2727 if (output->base.enabled)
2728 drm_output_deinit(&output->base);
2730 wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
2732 wl_list_remove(&drm_mode->base.link);
2737 /* Restore original CRTC state */
2738 drmModeSetCrtc(b->drm.fd, origcrtc->crtc_id, origcrtc->buffer_id,
2739 origcrtc->x, origcrtc->y,
2740 &output->connector_id, 1, &origcrtc->mode);
2741 drmModeFreeCrtc(origcrtc);
2744 if (output->pageflip_timer)
2745 wl_event_source_remove(output->pageflip_timer);
2747 weston_output_destroy(&output->base);
2749 drmModeFreeConnector(output->connector);
2751 if (output->backlight)
2752 backlight_destroy(output->backlight);
2758 drm_output_disable(struct weston_output *base)
2760 struct drm_output *output = to_drm_output(base);
2761 struct drm_backend *b = to_drm_backend(base->compositor);
2763 if (output->page_flip_pending) {
2764 output->disable_pending = 1;
2768 if (output->base.enabled)
2769 drm_output_deinit(&output->base);
2771 output->disable_pending = 0;
2773 weston_log("Disabling output %s\n", output->base.name);
2774 drmModeSetCrtc(b->drm.fd, output->crtc_id,
2775 0, 0, 0, 0, 0, NULL);
2781 * Create a Weston output structure
2783 * Given a DRM connector, create a matching drm_output structure and add it
2784 * to Weston's output list. It also takes ownership of the connector, which
2785 * is released when output is destroyed.
2787 * @param b Weston backend structure
2788 * @param resources DRM resources for this device
2789 * @param connector DRM connector to use for this new output
2790 * @param drm_device udev device pointer
2791 * @returns 0 on success, or -1 on failure
2794 create_output_for_connector(struct drm_backend *b,
2795 drmModeRes *resources,
2796 drmModeConnector *connector,
2797 struct udev_device *drm_device)
2799 struct drm_output *output;
2800 struct drm_mode *drm_mode;
2803 i = find_crtc_for_connector(b, resources, connector);
2805 weston_log("No usable crtc/encoder pair for connector.\n");
2809 output = zalloc(sizeof *output);
2813 output->connector = connector;
2814 output->crtc_id = resources->crtcs[i];
2816 output->connector_id = connector->connector_id;
2818 output->backlight = backlight_init(drm_device,
2819 connector->connector_type);
2821 output->original_crtc = drmModeGetCrtc(b->drm.fd, output->crtc_id);
2823 output->base.enable = drm_output_enable;
2824 output->base.destroy = drm_output_destroy;
2825 output->base.disable = drm_output_disable;
2826 output->base.name = make_connector_name(connector);
2828 output->destroy_pending = 0;
2829 output->disable_pending = 0;
2831 weston_output_init(&output->base, b->compositor);
2833 wl_list_init(&output->base.mode_list);
2835 for (i = 0; i < output->connector->count_modes; i++) {
2836 drm_mode = drm_output_add_mode(output, &output->connector->modes[i]);
2838 drm_output_destroy(&output->base);
2843 weston_compositor_add_pending_output(&output->base, b->compositor);
2848 drmModeFreeConnector(connector);
2854 create_sprites(struct drm_backend *b)
2856 struct drm_plane *plane;
2857 drmModePlaneRes *kplane_res;
2858 drmModePlane *kplane;
2861 kplane_res = drmModeGetPlaneResources(b->drm.fd);
2863 weston_log("failed to get plane resources: %s\n",
2868 for (i = 0; i < kplane_res->count_planes; i++) {
2869 kplane = drmModeGetPlane(b->drm.fd, kplane_res->planes[i]);
2873 plane = zalloc(sizeof(*plane) + ((sizeof(uint32_t)) *
2874 kplane->count_formats));
2876 weston_log("%s: out of memory\n",
2878 drmModeFreePlane(kplane);
2882 plane->possible_crtcs = kplane->possible_crtcs;
2883 plane->plane_id = kplane->plane_id;
2884 plane->fb_last = NULL;
2885 plane->fb_current = NULL;
2886 plane->fb_pending = NULL;
2888 plane->count_formats = kplane->count_formats;
2889 memcpy(plane->formats, kplane->formats,
2890 kplane->count_formats * sizeof(kplane->formats[0]));
2891 drmModeFreePlane(kplane);
2892 weston_plane_init(&plane->base, b->compositor, 0, 0);
2893 weston_compositor_stack_plane(b->compositor, &plane->base,
2894 &b->compositor->primary_plane);
2896 wl_list_insert(&b->sprite_list, &plane->link);
2899 drmModeFreePlaneResources(kplane_res);
2903 destroy_sprites(struct drm_backend *backend)
2905 struct drm_plane *plane, *next;
2906 struct drm_output *output;
2908 output = container_of(backend->compositor->output_list.next,
2909 struct drm_output, base.link);
2911 wl_list_for_each_safe(plane, next, &backend->sprite_list, link) {
2912 drmModeSetPlane(backend->drm.fd,
2914 output->crtc_id, 0, 0,
2915 0, 0, 0, 0, 0, 0, 0, 0);
2916 assert(!plane->fb_last);
2917 assert(!plane->fb_pending);
2918 drm_fb_unref(plane->fb_current);
2919 weston_plane_release(&plane->base);
2925 create_outputs(struct drm_backend *b, struct udev_device *drm_device)
2927 drmModeConnector *connector;
2928 drmModeRes *resources;
2931 resources = drmModeGetResources(b->drm.fd);
2933 weston_log("drmModeGetResources failed\n");
2937 b->min_width = resources->min_width;
2938 b->max_width = resources->max_width;
2939 b->min_height = resources->min_height;
2940 b->max_height = resources->max_height;
2942 for (i = 0; i < resources->count_connectors; i++) {
2943 connector = drmModeGetConnector(b->drm.fd,
2944 resources->connectors[i]);
2945 if (connector == NULL)
2948 if (connector->connection == DRM_MODE_CONNECTED &&
2949 (b->connector == 0 ||
2950 connector->connector_id == b->connector)) {
2951 if (create_output_for_connector(b, resources,
2952 connector, drm_device) < 0)
2955 drmModeFreeConnector(connector);
2959 if (wl_list_empty(&b->compositor->output_list) &&
2960 wl_list_empty(&b->compositor->pending_output_list))
2961 weston_log("No currently active connector found.\n");
2963 drmModeFreeResources(resources);
2969 update_outputs(struct drm_backend *b, struct udev_device *drm_device)
2971 drmModeConnector *connector;
2972 drmModeRes *resources;
2973 struct drm_output *output, *next;
2974 uint32_t *connected;
2977 resources = drmModeGetResources(b->drm.fd);
2979 weston_log("drmModeGetResources failed\n");
2983 connected = calloc(resources->count_connectors, sizeof(uint32_t));
2985 drmModeFreeResources(resources);
2989 /* collect new connects */
2990 for (i = 0; i < resources->count_connectors; i++) {
2991 uint32_t connector_id = resources->connectors[i];
2993 connector = drmModeGetConnector(b->drm.fd, connector_id);
2994 if (connector == NULL)
2997 if (connector->connection != DRM_MODE_CONNECTED) {
2998 drmModeFreeConnector(connector);
3002 if (b->connector && (b->connector != connector_id)) {
3003 drmModeFreeConnector(connector);
3007 connected[i] = connector_id;
3009 if (drm_output_find_by_connector(b, connector_id)) {
3010 drmModeFreeConnector(connector);
3014 create_output_for_connector(b, resources,
3015 connector, drm_device);
3016 weston_log("connector %d connected\n", connector_id);
3019 wl_list_for_each_safe(output, next, &b->compositor->output_list,
3021 bool disconnected = true;
3023 for (i = 0; i < resources->count_connectors; i++) {
3024 if (connected[i] == output->connector_id) {
3025 disconnected = false;
3033 weston_log("connector %d disconnected\n", output->connector_id);
3034 drm_output_destroy(&output->base);
3037 wl_list_for_each_safe(output, next, &b->compositor->pending_output_list,
3039 bool disconnected = true;
3041 for (i = 0; i < resources->count_connectors; i++) {
3042 if (connected[i] == output->connector_id) {
3043 disconnected = false;
3051 weston_log("connector %d disconnected\n", output->connector_id);
3052 drm_output_destroy(&output->base);
3056 drmModeFreeResources(resources);
3060 udev_event_is_hotplug(struct drm_backend *b, struct udev_device *device)
3065 sysnum = udev_device_get_sysnum(device);
3066 if (!sysnum || atoi(sysnum) != b->drm.id)
3069 val = udev_device_get_property_value(device, "HOTPLUG");
3073 return strcmp(val, "1") == 0;
3077 udev_drm_event(int fd, uint32_t mask, void *data)
3079 struct drm_backend *b = data;
3080 struct udev_device *event;
3082 event = udev_monitor_receive_device(b->udev_monitor);
3084 if (udev_event_is_hotplug(b, event))
3085 update_outputs(b, event);
3087 udev_device_unref(event);
3093 drm_restore(struct weston_compositor *ec)
3095 weston_launcher_restore(ec->launcher);
3099 drm_destroy(struct weston_compositor *ec)
3101 struct drm_backend *b = to_drm_backend(ec);
3103 udev_input_destroy(&b->input);
3105 wl_event_source_remove(b->udev_drm_source);
3106 wl_event_source_remove(b->drm_source);
3110 weston_compositor_shutdown(ec);
3113 gbm_device_destroy(b->gbm);
3115 weston_launcher_destroy(ec->launcher);
3122 session_notify(struct wl_listener *listener, void *data)
3124 struct weston_compositor *compositor = data;
3125 struct drm_backend *b = to_drm_backend(compositor);
3126 struct drm_plane *sprite;
3127 struct drm_output *output;
3129 if (compositor->session_active) {
3130 weston_log("activating session\n");
3131 weston_compositor_wake(compositor);
3132 weston_compositor_damage_all(compositor);
3133 udev_input_enable(&b->input);
3135 weston_log("deactivating session\n");
3136 udev_input_disable(&b->input);
3138 weston_compositor_offscreen(compositor);
3140 /* If we have a repaint scheduled (either from a
3141 * pending pageflip or the idle handler), make sure we
3142 * cancel that so we don't try to pageflip when we're
3143 * vt switched away. The OFFSCREEN state will prevent
3144 * further attempts at repainting. When we switch
3145 * back, we schedule a repaint, which will process
3146 * pending frame callbacks. */
3148 wl_list_for_each(output, &compositor->output_list, base.link) {
3149 output->base.repaint_needed = false;
3150 drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
3153 output = container_of(compositor->output_list.next,
3154 struct drm_output, base.link);
3156 wl_list_for_each(sprite, &b->sprite_list, link)
3157 drmModeSetPlane(b->drm.fd,
3159 output->crtc_id, 0, 0,
3160 0, 0, 0, 0, 0, 0, 0, 0);
3165 * Determines whether or not a device is capable of modesetting. If successful,
3166 * sets b->drm.fd and b->drm.filename to the opened device.
3169 drm_device_is_kms(struct drm_backend *b, struct udev_device *device)
3171 const char *filename = udev_device_get_devnode(device);
3172 const char *sysnum = udev_device_get_sysnum(device);
3179 fd = weston_launcher_open(b->compositor->launcher, filename, O_RDWR);
3183 res = drmModeGetResources(fd);
3187 if (res->count_crtcs <= 0 || res->count_connectors <= 0 ||
3188 res->count_encoders <= 0)
3193 if (!sysnum || id < 0) {
3194 weston_log("couldn't get sysnum for device %s\n", filename);
3198 /* We can be called successfully on multiple devices; if we have,
3199 * clean up old entries. */
3201 weston_launcher_close(b->compositor->launcher, b->drm.fd);
3202 free(b->drm.filename);
3206 b->drm.filename = strdup(filename);
3208 drmModeFreeResources(res);
3213 drmModeFreeResources(res);
3215 weston_launcher_close(b->compositor->launcher, fd);
3221 * Some systems may have multiple DRM devices attached to a single seat. This
3222 * function loops over all devices and tries to find a PCI device with the
3223 * boot_vga sysfs attribute set to 1.
3224 * If no such device is found, the first DRM device reported by udev is used.
3225 * Devices are also vetted to make sure they are are capable of modesetting,
3226 * rather than pure render nodes (GPU with no display), or pure
3227 * memory-allocation devices (VGEM).
3229 static struct udev_device*
3230 find_primary_gpu(struct drm_backend *b, const char *seat)
3232 struct udev_enumerate *e;
3233 struct udev_list_entry *entry;
3234 const char *path, *device_seat, *id;
3235 struct udev_device *device, *drm_device, *pci;
3237 e = udev_enumerate_new(b->udev);
3238 udev_enumerate_add_match_subsystem(e, "drm");
3239 udev_enumerate_add_match_sysname(e, "card[0-9]*");
3241 udev_enumerate_scan_devices(e);
3243 udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
3244 bool is_boot_vga = false;
3246 path = udev_list_entry_get_name(entry);
3247 device = udev_device_new_from_syspath(b->udev, path);
3250 device_seat = udev_device_get_property_value(device, "ID_SEAT");
3252 device_seat = default_seat;
3253 if (strcmp(device_seat, seat)) {
3254 udev_device_unref(device);
3258 pci = udev_device_get_parent_with_subsystem_devtype(device,
3261 id = udev_device_get_sysattr_value(pci, "boot_vga");
3262 if (id && !strcmp(id, "1"))
3266 /* If we already have a modesetting-capable device, and this
3267 * device isn't our boot-VGA device, we aren't going to use
3269 if (!is_boot_vga && drm_device) {
3270 udev_device_unref(device);
3274 /* Make sure this device is actually capable of modesetting;
3275 * if this call succeeds, b->drm.{fd,filename} will be set,
3276 * and any old values freed. */
3277 if (!drm_device_is_kms(b, device)) {
3278 udev_device_unref(device);
3282 /* There can only be one boot_vga device, and we try to use it
3286 udev_device_unref(drm_device);
3287 drm_device = device;
3291 /* Per the (!is_boot_vga && drm_device) test above, we only
3292 * trump existing saved devices with boot-VGA devices, so if
3293 * we end up here, this must be the first device we've seen. */
3294 assert(!drm_device);
3295 drm_device = device;
3298 /* If we're returning a device to use, we must have an open FD for
3300 assert(!!drm_device == (b->drm.fd >= 0));
3302 udev_enumerate_unref(e);
3307 planes_binding(struct weston_keyboard *keyboard, uint32_t time, uint32_t key,
3310 struct drm_backend *b = data;
3314 b->cursors_are_broken ^= 1;
3317 b->sprites_are_broken ^= 1;
3320 b->sprites_hidden ^= 1;
3327 #ifdef BUILD_VAAPI_RECORDER
3329 recorder_destroy(struct drm_output *output)
3331 vaapi_recorder_destroy(output->recorder);
3332 output->recorder = NULL;
3334 output->base.disable_planes--;
3336 wl_list_remove(&output->recorder_frame_listener.link);
3337 weston_log("[libva recorder] done\n");
3341 recorder_frame_notify(struct wl_listener *listener, void *data)
3343 struct drm_output *output;
3344 struct drm_backend *b;
3347 output = container_of(listener, struct drm_output,
3348 recorder_frame_listener);
3349 b = to_drm_backend(output->base.compositor);
3351 if (!output->recorder)
3354 ret = drmPrimeHandleToFD(b->drm.fd, output->fb_current->handle,
3357 weston_log("[libva recorder] "
3358 "failed to create prime fd for front buffer\n");
3362 ret = vaapi_recorder_frame(output->recorder, fd,
3363 output->fb_current->stride);
3365 weston_log("[libva recorder] aborted: %m\n");
3366 recorder_destroy(output);
3371 create_recorder(struct drm_backend *b, int width, int height,
3372 const char *filename)
3377 fd = open(b->drm.filename, O_RDWR | O_CLOEXEC);
3381 drmGetMagic(fd, &magic);
3382 drmAuthMagic(b->drm.fd, magic);
3384 return vaapi_recorder_create(fd, width, height, filename);
3388 recorder_binding(struct weston_keyboard *keyboard, uint32_t time, uint32_t key,
3391 struct drm_backend *b = data;
3392 struct drm_output *output;
3395 output = container_of(b->compositor->output_list.next,
3396 struct drm_output, base.link);
3398 if (!output->recorder) {
3399 if (output->gbm_format != GBM_FORMAT_XRGB8888) {
3400 weston_log("failed to start vaapi recorder: "
3401 "output format not supported\n");
3405 width = output->base.current_mode->width;
3406 height = output->base.current_mode->height;
3409 create_recorder(b, width, height, "capture.h264");
3410 if (!output->recorder) {
3411 weston_log("failed to create vaapi recorder\n");
3415 output->base.disable_planes++;
3417 output->recorder_frame_listener.notify = recorder_frame_notify;
3418 wl_signal_add(&output->base.frame_signal,
3419 &output->recorder_frame_listener);
3421 weston_output_schedule_repaint(&output->base);
3423 weston_log("[libva recorder] initialized\n");
3425 recorder_destroy(output);
3430 recorder_binding(struct weston_keyboard *keyboard, uint32_t time, uint32_t key,
3433 weston_log("Compiled without libva support\n");
3438 switch_to_gl_renderer(struct drm_backend *b)
3440 struct drm_output *output;
3441 bool dmabuf_support_inited;
3446 dmabuf_support_inited = !!b->compositor->renderer->import_dmabuf;
3448 weston_log("Switching to GL renderer\n");
3450 b->gbm = create_gbm_device(b->drm.fd);
3452 weston_log("Failed to create gbm device. "
3453 "Aborting renderer switch\n");
3457 wl_list_for_each(output, &b->compositor->output_list, base.link)
3458 pixman_renderer_output_destroy(&output->base);
3460 b->compositor->renderer->destroy(b->compositor);
3462 if (drm_backend_create_gl_renderer(b) < 0) {
3463 gbm_device_destroy(b->gbm);
3464 weston_log("Failed to create GL renderer. Quitting.\n");
3465 /* FIXME: we need a function to shutdown cleanly */
3469 wl_list_for_each(output, &b->compositor->output_list, base.link)
3470 drm_output_init_egl(output, b);
3474 if (!dmabuf_support_inited && b->compositor->renderer->import_dmabuf) {
3475 if (linux_dmabuf_setup(b->compositor) < 0)
3476 weston_log("Error: initializing dmabuf "
3477 "support failed.\n");
3482 renderer_switch_binding(struct weston_keyboard *keyboard, uint32_t time,
3483 uint32_t key, void *data)
3485 struct drm_backend *b =
3486 to_drm_backend(keyboard->seat->compositor);
3488 switch_to_gl_renderer(b);
3491 static const struct weston_drm_output_api api = {
3492 drm_output_set_mode,
3493 drm_output_set_gbm_format,
3494 drm_output_set_seat,
3497 static struct drm_backend *
3498 drm_backend_create(struct weston_compositor *compositor,
3499 struct weston_drm_backend_config *config)
3501 struct drm_backend *b;
3502 struct udev_device *drm_device;
3503 struct wl_event_loop *loop;
3504 const char *seat_id = default_seat;
3507 weston_log("initializing drm backend\n");
3509 b = zalloc(sizeof *b);
3516 * KMS support for hardware planes cannot properly synchronize
3517 * without nuclear page flip. Without nuclear/atomic, hw plane
3518 * and cursor plane updates would either tear or cause extra
3519 * waits for vblanks which means dropping the compositor framerate
3520 * to a fraction. For cursors, it's not so bad, so they are
3523 * These can be enabled again when nuclear/atomic support lands.
3525 b->sprites_are_broken = 1;
3526 b->compositor = compositor;
3527 b->use_pixman = config->use_pixman;
3528 b->pageflip_timeout = config->pageflip_timeout;
3530 if (parse_gbm_format(config->gbm_format, GBM_FORMAT_XRGB8888, &b->gbm_format) < 0)
3531 goto err_compositor;
3533 if (config->seat_id)
3534 seat_id = config->seat_id;
3536 /* Check if we run drm-backend using weston-launch */
3537 compositor->launcher = weston_launcher_connect(compositor, config->tty,
3539 if (compositor->launcher == NULL) {
3540 weston_log("fatal: drm backend should be run "
3541 "using weston-launch binary or as root\n");
3542 goto err_compositor;
3545 b->udev = udev_new();
3546 if (b->udev == NULL) {
3547 weston_log("failed to initialize udev context\n");
3551 b->session_listener.notify = session_notify;
3552 wl_signal_add(&compositor->session_signal, &b->session_listener);
3554 drm_device = find_primary_gpu(b, seat_id);
3555 if (drm_device == NULL) {
3556 weston_log("no drm device found\n");
3560 if (init_kms_caps(b) < 0) {
3561 weston_log("failed to initialize kms\n");
3565 if (b->use_pixman) {
3566 if (init_pixman(b) < 0) {
3567 weston_log("failed to initialize pixman renderer\n");
3571 if (init_egl(b) < 0) {
3572 weston_log("failed to initialize egl\n");
3577 b->base.destroy = drm_destroy;
3578 b->base.restore = drm_restore;
3580 weston_setup_vt_switch_bindings(compositor);
3582 wl_list_init(&b->sprite_list);
3585 if (udev_input_init(&b->input,
3586 compositor, b->udev, seat_id,
3587 config->configure_device) < 0) {
3588 weston_log("failed to create input devices\n");
3592 b->connector = config->connector;
3594 if (create_outputs(b, drm_device) < 0) {
3595 weston_log("failed to create output for %s\n", b->drm.filename);
3596 goto err_udev_input;
3599 /* A this point we have some idea of whether or not we have a working
3601 if (!b->cursors_are_broken)
3602 compositor->capabilities |= WESTON_CAP_CURSOR_PLANE;
3604 loop = wl_display_get_event_loop(compositor->wl_display);
3606 wl_event_loop_add_fd(loop, b->drm.fd,
3607 WL_EVENT_READABLE, on_drm_input, b);
3609 b->udev_monitor = udev_monitor_new_from_netlink(b->udev, "udev");
3610 if (b->udev_monitor == NULL) {
3611 weston_log("failed to initialize udev monitor\n");
3612 goto err_drm_source;
3614 udev_monitor_filter_add_match_subsystem_devtype(b->udev_monitor,
3616 b->udev_drm_source =
3617 wl_event_loop_add_fd(loop,
3618 udev_monitor_get_fd(b->udev_monitor),
3619 WL_EVENT_READABLE, udev_drm_event, b);
3621 if (udev_monitor_enable_receiving(b->udev_monitor) < 0) {
3622 weston_log("failed to enable udev-monitor receiving\n");
3623 goto err_udev_monitor;
3626 udev_device_unref(drm_device);
3628 weston_compositor_add_debug_binding(compositor, KEY_O,
3630 weston_compositor_add_debug_binding(compositor, KEY_C,
3632 weston_compositor_add_debug_binding(compositor, KEY_V,
3634 weston_compositor_add_debug_binding(compositor, KEY_Q,
3635 recorder_binding, b);
3636 weston_compositor_add_debug_binding(compositor, KEY_W,
3637 renderer_switch_binding, b);
3639 if (compositor->renderer->import_dmabuf) {
3640 if (linux_dmabuf_setup(compositor) < 0)
3641 weston_log("Error: initializing dmabuf "
3642 "support failed.\n");
3645 compositor->backend = &b->base;
3647 ret = weston_plugin_api_register(compositor, WESTON_DRM_OUTPUT_API_NAME,
3651 weston_log("Failed to register output API.\n");
3652 goto err_udev_monitor;
3658 wl_event_source_remove(b->udev_drm_source);
3659 udev_monitor_unref(b->udev_monitor);
3661 wl_event_source_remove(b->drm_source);
3663 udev_input_destroy(&b->input);
3666 gbm_device_destroy(b->gbm);
3669 udev_device_unref(drm_device);
3671 weston_launcher_destroy(compositor->launcher);
3673 udev_unref(b->udev);
3675 weston_compositor_shutdown(compositor);
3681 config_init_to_defaults(struct weston_drm_backend_config *config)
3686 weston_backend_init(struct weston_compositor *compositor,
3687 struct weston_backend_config *config_base)
3689 struct drm_backend *b;
3690 struct weston_drm_backend_config config = {{ 0, }};
3692 if (config_base == NULL ||
3693 config_base->struct_version != WESTON_DRM_BACKEND_CONFIG_VERSION ||
3694 config_base->struct_size > sizeof(struct weston_drm_backend_config)) {
3695 weston_log("drm backend config structure is invalid\n");
3699 config_init_to_defaults(&config);
3700 memcpy(&config, config_base, config_base->struct_size);
3702 b = drm_backend_create(compositor, &config);