154e15e4c79ba40d70c98b6688d8720a0892f3c1
[profile/ivi/weston-ivi-shell.git] / src / compositor-drm.c
1 /*
2  * Copyright © 2008-2011 Kristian Høgsberg
3  * Copyright © 2011 Intel Corporation
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and
6  * its documentation for any purpose is hereby granted without fee, provided
7  * that the above copyright notice appear in all copies and that both that
8  * copyright notice and this permission notice appear in supporting
9  * documentation, and that the name of the copyright holders not be used in
10  * advertising or publicity pertaining to distribution of the software
11  * without specific, written prior permission.  The copyright holders make
12  * no representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied warranty.
14  *
15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  */
23
24 #include "config.h"
25
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <ctype.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <linux/input.h>
33 #include <linux/vt.h>
34 #include <assert.h>
35 #include <sys/mman.h>
36 #include <dlfcn.h>
37 #include <time.h>
38
39 #include <xf86drm.h>
40 #include <xf86drmMode.h>
41 #include <drm_fourcc.h>
42
43 #include <gbm.h>
44 #include <libbacklight.h>
45 #include <libudev.h>
46
47 #include "compositor.h"
48 #include "gl-renderer.h"
49 #include "pixman-renderer.h"
50 #include "udev-seat.h"
51 #include "launcher-util.h"
52 #include "vaapi-recorder.h"
53
54 #ifndef DRM_CAP_TIMESTAMP_MONOTONIC
55 #define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
56 #endif
57
58 static int option_current_mode = 0;
59
60 enum output_config {
61         OUTPUT_CONFIG_INVALID = 0,
62         OUTPUT_CONFIG_OFF,
63         OUTPUT_CONFIG_PREFERRED,
64         OUTPUT_CONFIG_CURRENT,
65         OUTPUT_CONFIG_MODE,
66         OUTPUT_CONFIG_MODELINE
67 };
68
69 struct drm_compositor {
70         struct weston_compositor base;
71
72         struct udev *udev;
73         struct wl_event_source *drm_source;
74
75         struct udev_monitor *udev_monitor;
76         struct wl_event_source *udev_drm_source;
77
78         struct {
79                 int id;
80                 int fd;
81                 char *filename;
82         } drm;
83         struct gbm_device *gbm;
84         uint32_t *crtcs;
85         int num_crtcs;
86         uint32_t crtc_allocator;
87         uint32_t connector_allocator;
88         struct wl_listener session_listener;
89         uint32_t format;
90
91         /* we need these parameters in order to not fail drmModeAddFB2()
92          * due to out of bounds dimensions, and then mistakenly set
93          * sprites_are_broken:
94          */
95         uint32_t min_width, max_width;
96         uint32_t min_height, max_height;
97         int no_addfb2;
98
99         struct wl_list sprite_list;
100         int sprites_are_broken;
101         int sprites_hidden;
102
103         int cursors_are_broken;
104
105         int use_pixman;
106
107         uint32_t prev_state;
108
109         clockid_t clock;
110         struct udev_input input;
111 };
112
113 struct drm_mode {
114         struct weston_mode base;
115         drmModeModeInfo mode_info;
116 };
117
118 struct drm_output;
119
120 struct drm_fb {
121         struct drm_output *output;
122         uint32_t fb_id, stride, handle, size;
123         int fd;
124         int is_client_buffer;
125         struct weston_buffer_reference buffer_ref;
126
127         /* Used by gbm fbs */
128         struct gbm_bo *bo;
129
130         /* Used by dumb fbs */
131         void *map;
132 };
133
134 struct drm_edid {
135         char eisa_id[13];
136         char monitor_name[13];
137         char pnp_id[5];
138         char serial_number[13];
139 };
140
141 struct drm_output {
142         struct weston_output   base;
143
144         uint32_t crtc_id;
145         int pipe;
146         uint32_t connector_id;
147         drmModeCrtcPtr original_crtc;
148         struct drm_edid edid;
149         drmModePropertyPtr dpms_prop;
150
151         int vblank_pending;
152         int page_flip_pending;
153         int destroy_pending;
154
155         struct gbm_surface *surface;
156         struct gbm_bo *cursor_bo[2];
157         struct weston_plane cursor_plane;
158         struct weston_plane fb_plane;
159         struct weston_view *cursor_view;
160         int current_cursor;
161         struct drm_fb *current, *next;
162         struct backlight *backlight;
163
164         struct drm_fb *dumb[2];
165         pixman_image_t *image[2];
166         int current_image;
167         pixman_region32_t previous_damage;
168
169         struct vaapi_recorder *recorder;
170         struct wl_listener recorder_frame_listener;
171 };
172
173 /*
174  * An output has a primary display plane plus zero or more sprites for
175  * blending display contents.
176  */
177 struct drm_sprite {
178         struct wl_list link;
179
180         struct weston_plane plane;
181
182         struct drm_fb *current, *next;
183         struct drm_output *output;
184         struct drm_compositor *compositor;
185
186         uint32_t possible_crtcs;
187         uint32_t plane_id;
188         uint32_t count_formats;
189
190         int32_t src_x, src_y;
191         uint32_t src_w, src_h;
192         uint32_t dest_x, dest_y;
193         uint32_t dest_w, dest_h;
194
195         uint32_t formats[];
196 };
197
198 struct drm_parameters {
199         int connector;
200         int tty;
201         int use_pixman;
202         const char *seat_id;
203 };
204
205 static struct gl_renderer_interface *gl_renderer;
206
207 static const char default_seat[] = "seat0";
208
209 static void
210 drm_output_set_cursor(struct drm_output *output);
211
212 static int
213 drm_sprite_crtc_supported(struct weston_output *output_base, uint32_t supported)
214 {
215         struct weston_compositor *ec = output_base->compositor;
216         struct drm_compositor *c =(struct drm_compositor *) ec;
217         struct drm_output *output = (struct drm_output *) output_base;
218         int crtc;
219
220         for (crtc = 0; crtc < c->num_crtcs; crtc++) {
221                 if (c->crtcs[crtc] != output->crtc_id)
222                         continue;
223
224                 if (supported & (1 << crtc))
225                         return -1;
226         }
227
228         return 0;
229 }
230
231 static void
232 drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
233 {
234         struct drm_fb *fb = data;
235         struct gbm_device *gbm = gbm_bo_get_device(bo);
236
237         if (fb->fb_id)
238                 drmModeRmFB(gbm_device_get_fd(gbm), fb->fb_id);
239
240         weston_buffer_reference(&fb->buffer_ref, NULL);
241
242         free(data);
243 }
244
245 static struct drm_fb *
246 drm_fb_create_dumb(struct drm_compositor *ec, unsigned width, unsigned height)
247 {
248         struct drm_fb *fb;
249         int ret;
250
251         struct drm_mode_create_dumb create_arg;
252         struct drm_mode_destroy_dumb destroy_arg;
253         struct drm_mode_map_dumb map_arg;
254
255         fb = zalloc(sizeof *fb);
256         if (!fb)
257                 return NULL;
258
259         memset(&create_arg, 0, sizeof create_arg);
260         create_arg.bpp = 32;
261         create_arg.width = width;
262         create_arg.height = height;
263
264         ret = drmIoctl(ec->drm.fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg);
265         if (ret)
266                 goto err_fb;
267
268         fb->handle = create_arg.handle;
269         fb->stride = create_arg.pitch;
270         fb->size = create_arg.size;
271         fb->fd = ec->drm.fd;
272
273         ret = drmModeAddFB(ec->drm.fd, width, height, 24, 32,
274                            fb->stride, fb->handle, &fb->fb_id);
275         if (ret)
276                 goto err_bo;
277
278         memset(&map_arg, 0, sizeof map_arg);
279         map_arg.handle = fb->handle;
280         ret = drmIoctl(fb->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_arg);
281         if (ret)
282                 goto err_add_fb;
283
284         fb->map = mmap(0, fb->size, PROT_WRITE,
285                        MAP_SHARED, ec->drm.fd, map_arg.offset);
286         if (fb->map == MAP_FAILED)
287                 goto err_add_fb;
288
289         return fb;
290
291 err_add_fb:
292         drmModeRmFB(ec->drm.fd, fb->fb_id);
293 err_bo:
294         memset(&destroy_arg, 0, sizeof(destroy_arg));
295         destroy_arg.handle = create_arg.handle;
296         drmIoctl(ec->drm.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
297 err_fb:
298         free(fb);
299         return NULL;
300 }
301
302 static void
303 drm_fb_destroy_dumb(struct drm_fb *fb)
304 {
305         struct drm_mode_destroy_dumb destroy_arg;
306
307         if (!fb->map)
308                 return;
309
310         if (fb->fb_id)
311                 drmModeRmFB(fb->fd, fb->fb_id);
312
313         weston_buffer_reference(&fb->buffer_ref, NULL);
314
315         munmap(fb->map, fb->size);
316
317         memset(&destroy_arg, 0, sizeof(destroy_arg));
318         destroy_arg.handle = fb->handle;
319         drmIoctl(fb->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
320
321         free(fb);
322 }
323
324 static struct drm_fb *
325 drm_fb_get_from_bo(struct gbm_bo *bo,
326                    struct drm_compositor *compositor, uint32_t format)
327 {
328         struct drm_fb *fb = gbm_bo_get_user_data(bo);
329         uint32_t width, height;
330         uint32_t handles[4], pitches[4], offsets[4];
331         int ret;
332
333         if (fb)
334                 return fb;
335
336         fb = calloc(1, sizeof *fb);
337         if (!fb)
338                 return NULL;
339
340         fb->bo = bo;
341
342         width = gbm_bo_get_width(bo);
343         height = gbm_bo_get_height(bo);
344         fb->stride = gbm_bo_get_stride(bo);
345         fb->handle = gbm_bo_get_handle(bo).u32;
346         fb->size = fb->stride * height;
347         fb->fd = compositor->drm.fd;
348
349         if (compositor->min_width > width || width > compositor->max_width ||
350             compositor->min_height > height ||
351             height > compositor->max_height) {
352                 weston_log("bo geometry out of bounds\n");
353                 goto err_free;
354         }
355
356         ret = -1;
357
358         if (format && !compositor->no_addfb2) {
359                 handles[0] = fb->handle;
360                 pitches[0] = fb->stride;
361                 offsets[0] = 0;
362
363                 ret = drmModeAddFB2(compositor->drm.fd, width, height,
364                                     format, handles, pitches, offsets,
365                                     &fb->fb_id, 0);
366                 if (ret) {
367                         weston_log("addfb2 failed: %m\n");
368                         compositor->no_addfb2 = 1;
369                         compositor->sprites_are_broken = 1;
370                 }
371         }
372
373         if (ret)
374                 ret = drmModeAddFB(compositor->drm.fd, width, height, 24, 32,
375                                    fb->stride, fb->handle, &fb->fb_id);
376
377         if (ret) {
378                 weston_log("failed to create kms fb: %m\n");
379                 goto err_free;
380         }
381
382         gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback);
383
384         return fb;
385
386 err_free:
387         free(fb);
388         return NULL;
389 }
390
391 static void
392 drm_fb_set_buffer(struct drm_fb *fb, struct weston_buffer *buffer)
393 {
394         assert(fb->buffer_ref.buffer == NULL);
395
396         fb->is_client_buffer = 1;
397
398         weston_buffer_reference(&fb->buffer_ref, buffer);
399 }
400
401 static void
402 drm_output_release_fb(struct drm_output *output, struct drm_fb *fb)
403 {
404         if (!fb)
405                 return;
406
407         if (fb->map &&
408             (fb != output->dumb[0] && fb != output->dumb[1])) {
409                 drm_fb_destroy_dumb(fb);
410         } else if (fb->bo) {
411                 if (fb->is_client_buffer)
412                         gbm_bo_destroy(fb->bo);
413                 else
414                         gbm_surface_release_buffer(output->surface,
415                                                    fb->bo);
416         }
417 }
418
419 static uint32_t
420 drm_output_check_scanout_format(struct drm_output *output,
421                                 struct weston_surface *es, struct gbm_bo *bo)
422 {
423         struct drm_compositor *c =
424                 (struct drm_compositor *) output->base.compositor;
425         uint32_t format;
426         pixman_region32_t r;
427
428         format = gbm_bo_get_format(bo);
429
430         if (format == GBM_FORMAT_ARGB8888) {
431                 /* We can scanout an ARGB buffer if the surface's
432                  * opaque region covers the whole output, but we have
433                  * to use XRGB as the KMS format code. */
434                 pixman_region32_init_rect(&r, 0, 0,
435                                           output->base.width,
436                                           output->base.height);
437                 pixman_region32_subtract(&r, &r, &es->opaque);
438
439                 if (!pixman_region32_not_empty(&r))
440                         format = GBM_FORMAT_XRGB8888;
441
442                 pixman_region32_fini(&r);
443         }
444
445         if (c->format == format)
446                 return format;
447
448         return 0;
449 }
450
451 static struct weston_plane *
452 drm_output_prepare_scanout_view(struct weston_output *_output,
453                                 struct weston_view *ev)
454 {
455         struct drm_output *output = (struct drm_output *) _output;
456         struct drm_compositor *c =
457                 (struct drm_compositor *) output->base.compositor;
458         struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
459         struct gbm_bo *bo;
460         uint32_t format;
461
462         if (ev->geometry.x != output->base.x ||
463             ev->geometry.y != output->base.y ||
464             buffer == NULL || c->gbm == NULL ||
465             buffer->width != output->base.current_mode->width ||
466             buffer->height != output->base.current_mode->height ||
467             output->base.transform != ev->surface->buffer_viewport.transform ||
468             ev->transform.enabled)
469                 return NULL;
470
471         bo = gbm_bo_import(c->gbm, GBM_BO_IMPORT_WL_BUFFER,
472                            buffer->resource, GBM_BO_USE_SCANOUT);
473
474         /* Unable to use the buffer for scanout */
475         if (!bo)
476                 return NULL;
477
478         format = drm_output_check_scanout_format(output, ev->surface, bo);
479         if (format == 0) {
480                 gbm_bo_destroy(bo);
481                 return NULL;
482         }
483
484         output->next = drm_fb_get_from_bo(bo, c, format);
485         if (!output->next) {
486                 gbm_bo_destroy(bo);
487                 return NULL;
488         }
489
490         drm_fb_set_buffer(output->next, buffer);
491
492         return &output->fb_plane;
493 }
494
495 static void
496 drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage)
497 {
498         struct drm_compositor *c =
499                 (struct drm_compositor *) output->base.compositor;
500         struct gbm_bo *bo;
501
502         c->base.renderer->repaint_output(&output->base, damage);
503
504         bo = gbm_surface_lock_front_buffer(output->surface);
505         if (!bo) {
506                 weston_log("failed to lock front buffer: %m\n");
507                 return;
508         }
509
510         output->next = drm_fb_get_from_bo(bo, c, c->format);
511         if (!output->next) {
512                 weston_log("failed to get drm_fb for bo\n");
513                 gbm_surface_release_buffer(output->surface, bo);
514                 return;
515         }
516 }
517
518 static void
519 drm_output_render_pixman(struct drm_output *output, pixman_region32_t *damage)
520 {
521         struct weston_compositor *ec = output->base.compositor;
522         pixman_region32_t total_damage, previous_damage;
523
524         pixman_region32_init(&total_damage);
525         pixman_region32_init(&previous_damage);
526
527         pixman_region32_copy(&previous_damage, damage);
528
529         pixman_region32_union(&total_damage, damage, &output->previous_damage);
530         pixman_region32_copy(&output->previous_damage, &previous_damage);
531
532         output->current_image ^= 1;
533
534         output->next = output->dumb[output->current_image];
535         pixman_renderer_output_set_buffer(&output->base,
536                                           output->image[output->current_image]);
537
538         ec->renderer->repaint_output(&output->base, &total_damage);
539
540         pixman_region32_fini(&total_damage);
541         pixman_region32_fini(&previous_damage);
542 }
543
544 static void
545 drm_output_render(struct drm_output *output, pixman_region32_t *damage)
546 {
547         struct drm_compositor *c =
548                 (struct drm_compositor *) output->base.compositor;
549
550         if (c->use_pixman)
551                 drm_output_render_pixman(output, damage);
552         else
553                 drm_output_render_gl(output, damage);
554
555         pixman_region32_subtract(&c->base.primary_plane.damage,
556                                  &c->base.primary_plane.damage, damage);
557 }
558
559 static void
560 drm_output_set_gamma(struct weston_output *output_base,
561                      uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b)
562 {
563         int rc;
564         struct drm_output *output = (struct drm_output *) output_base;
565         struct drm_compositor *compositor = (struct drm_compositor *) output->base.compositor;
566
567         /* check */
568         if (output_base->gamma_size != size)
569                 return;
570         if (!output->original_crtc)
571                 return;
572
573         rc = drmModeCrtcSetGamma(compositor->drm.fd,
574                                  output->crtc_id,
575                                  size, r, g, b);
576         if (rc)
577                 weston_log("set gamma failed: %m\n");
578 }
579
580 static int
581 drm_output_repaint(struct weston_output *output_base,
582                    pixman_region32_t *damage)
583 {
584         struct drm_output *output = (struct drm_output *) output_base;
585         struct drm_compositor *compositor =
586                 (struct drm_compositor *) output->base.compositor;
587         struct drm_sprite *s;
588         struct drm_mode *mode;
589         int ret = 0;
590
591         if (output->destroy_pending)
592                 return -1;
593
594         if (!output->next)
595                 drm_output_render(output, damage);
596         if (!output->next)
597                 return -1;
598
599         mode = container_of(output->base.current_mode, struct drm_mode, base);
600         if (!output->current ||
601             output->current->stride != output->next->stride) {
602                 ret = drmModeSetCrtc(compositor->drm.fd, output->crtc_id,
603                                      output->next->fb_id, 0, 0,
604                                      &output->connector_id, 1,
605                                      &mode->mode_info);
606                 if (ret) {
607                         weston_log("set mode failed: %m\n");
608                         goto err_pageflip;
609                 }
610                 output_base->set_dpms(output_base, WESTON_DPMS_ON);
611         }
612
613         if (drmModePageFlip(compositor->drm.fd, output->crtc_id,
614                             output->next->fb_id,
615                             DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
616                 weston_log("queueing pageflip failed: %m\n");
617                 goto err_pageflip;
618         }
619
620         output->page_flip_pending = 1;
621
622         drm_output_set_cursor(output);
623
624         /*
625          * Now, update all the sprite surfaces
626          */
627         wl_list_for_each(s, &compositor->sprite_list, link) {
628                 uint32_t flags = 0, fb_id = 0;
629                 drmVBlank vbl = {
630                         .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
631                         .request.sequence = 1,
632                 };
633
634                 if ((!s->current && !s->next) ||
635                     !drm_sprite_crtc_supported(output_base, s->possible_crtcs))
636                         continue;
637
638                 if (s->next && !compositor->sprites_hidden)
639                         fb_id = s->next->fb_id;
640
641                 ret = drmModeSetPlane(compositor->drm.fd, s->plane_id,
642                                       output->crtc_id, fb_id, flags,
643                                       s->dest_x, s->dest_y,
644                                       s->dest_w, s->dest_h,
645                                       s->src_x, s->src_y,
646                                       s->src_w, s->src_h);
647                 if (ret)
648                         weston_log("setplane failed: %d: %s\n",
649                                 ret, strerror(errno));
650
651                 if (output->pipe > 0)
652                         vbl.request.type |= DRM_VBLANK_SECONDARY;
653
654                 /*
655                  * Queue a vblank signal so we know when the surface
656                  * becomes active on the display or has been replaced.
657                  */
658                 vbl.request.signal = (unsigned long)s;
659                 ret = drmWaitVBlank(compositor->drm.fd, &vbl);
660                 if (ret) {
661                         weston_log("vblank event request failed: %d: %s\n",
662                                 ret, strerror(errno));
663                 }
664
665                 s->output = output;
666                 output->vblank_pending = 1;
667         }
668
669         return 0;
670
671 err_pageflip:
672         output->cursor_view = NULL;
673         if (output->next) {
674                 drm_output_release_fb(output, output->next);
675                 output->next = NULL;
676         }
677
678         return -1;
679 }
680
681 static void
682 drm_output_start_repaint_loop(struct weston_output *output_base)
683 {
684         struct drm_output *output = (struct drm_output *) output_base;
685         struct drm_compositor *compositor = (struct drm_compositor *)
686                 output_base->compositor;
687         uint32_t fb_id;
688         uint32_t msec;
689         struct timespec ts;
690
691         if (output->destroy_pending)
692                 return;
693
694         if (!output->current) {
695                 /* We can't page flip if there's no mode set */
696                 goto finish_frame;
697         }
698
699         fb_id = output->current->fb_id;
700
701         if (drmModePageFlip(compositor->drm.fd, output->crtc_id, fb_id,
702                             DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
703                 weston_log("queueing pageflip failed: %m\n");
704                 goto finish_frame;
705         }
706
707         return;
708
709 finish_frame:
710         /* if we cannot page-flip, immediately finish frame */
711         clock_gettime(compositor->clock, &ts);
712         msec = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
713         weston_output_finish_frame(output_base, msec);
714 }
715
716 static void
717 vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec,
718                void *data)
719 {
720         struct drm_sprite *s = (struct drm_sprite *)data;
721         struct drm_output *output = s->output;
722         uint32_t msecs;
723
724         output->vblank_pending = 0;
725
726         drm_output_release_fb(output, s->current);
727         s->current = s->next;
728         s->next = NULL;
729
730         if (!output->page_flip_pending) {
731                 msecs = sec * 1000 + usec / 1000;
732                 weston_output_finish_frame(&output->base, msecs);
733         }
734 }
735
736 static void
737 drm_output_destroy(struct weston_output *output_base);
738
739 static void
740 page_flip_handler(int fd, unsigned int frame,
741                   unsigned int sec, unsigned int usec, void *data)
742 {
743         struct drm_output *output = (struct drm_output *) data;
744         uint32_t msecs;
745
746         /* We don't set page_flip_pending on start_repaint_loop, in that case
747          * we just want to page flip to the current buffer to get an accurate
748          * timestamp */
749         if (output->page_flip_pending) {
750                 drm_output_release_fb(output, output->current);
751                 output->current = output->next;
752                 output->next = NULL;
753         }
754
755         output->page_flip_pending = 0;
756
757         if (output->destroy_pending)
758                 drm_output_destroy(&output->base);
759         else if (!output->vblank_pending) {
760                 msecs = sec * 1000 + usec / 1000;
761                 weston_output_finish_frame(&output->base, msecs);
762
763                 /* We can't call this from frame_notify, because the output's
764                  * repaint needed flag is cleared just after that */
765                 if (output->recorder)
766                         weston_output_schedule_repaint(&output->base);
767         }
768 }
769
770 static uint32_t
771 drm_output_check_sprite_format(struct drm_sprite *s,
772                                struct weston_view *ev, struct gbm_bo *bo)
773 {
774         uint32_t i, format;
775
776         format = gbm_bo_get_format(bo);
777
778         if (format == GBM_FORMAT_ARGB8888) {
779                 pixman_region32_t r;
780
781                 pixman_region32_init_rect(&r, 0, 0,
782                                           ev->surface->width,
783                                           ev->surface->height);
784                 pixman_region32_subtract(&r, &r, &ev->surface->opaque);
785
786                 if (!pixman_region32_not_empty(&r))
787                         format = GBM_FORMAT_XRGB8888;
788
789                 pixman_region32_fini(&r);
790         }
791
792         for (i = 0; i < s->count_formats; i++)
793                 if (s->formats[i] == format)
794                         return format;
795
796         return 0;
797 }
798
799 static int
800 drm_view_transform_supported(struct weston_view *ev)
801 {
802         return !ev->transform.enabled ||
803                 (ev->transform.matrix.type < WESTON_MATRIX_TRANSFORM_ROTATE);
804 }
805
806 static struct weston_plane *
807 drm_output_prepare_overlay_view(struct weston_output *output_base,
808                                 struct weston_view *ev)
809 {
810         struct weston_compositor *ec = output_base->compositor;
811         struct drm_compositor *c =(struct drm_compositor *) ec;
812         struct drm_sprite *s;
813         int found = 0;
814         struct gbm_bo *bo;
815         pixman_region32_t dest_rect, src_rect;
816         pixman_box32_t *box, tbox;
817         uint32_t format;
818         wl_fixed_t sx1, sy1, sx2, sy2;
819
820         if (c->gbm == NULL)
821                 return NULL;
822
823         if (ev->surface->buffer_viewport.transform != output_base->transform)
824                 return NULL;
825
826         if (ev->surface->buffer_viewport.scale != output_base->current_scale)
827                 return NULL;
828
829         if (c->sprites_are_broken)
830                 return NULL;
831
832         if (ev->output_mask != (1u << output_base->id))
833                 return NULL;
834
835         if (ev->surface->buffer_ref.buffer == NULL)
836                 return NULL;
837
838         if (ev->alpha != 1.0f)
839                 return NULL;
840
841         if (wl_shm_buffer_get(ev->surface->buffer_ref.buffer->resource))
842                 return NULL;
843
844         if (!drm_view_transform_supported(ev))
845                 return NULL;
846
847         wl_list_for_each(s, &c->sprite_list, link) {
848                 if (!drm_sprite_crtc_supported(output_base, s->possible_crtcs))
849                         continue;
850
851                 if (!s->next) {
852                         found = 1;
853                         break;
854                 }
855         }
856
857         /* No sprites available */
858         if (!found)
859                 return NULL;
860
861         bo = gbm_bo_import(c->gbm, GBM_BO_IMPORT_WL_BUFFER,
862                            ev->surface->buffer_ref.buffer->resource,
863                            GBM_BO_USE_SCANOUT);
864         if (!bo)
865                 return NULL;
866
867         format = drm_output_check_sprite_format(s, ev, bo);
868         if (format == 0) {
869                 gbm_bo_destroy(bo);
870                 return NULL;
871         }
872
873         s->next = drm_fb_get_from_bo(bo, c, format);
874         if (!s->next) {
875                 gbm_bo_destroy(bo);
876                 return NULL;
877         }
878
879         drm_fb_set_buffer(s->next, ev->surface->buffer_ref.buffer);
880
881         box = pixman_region32_extents(&ev->transform.boundingbox);
882         s->plane.x = box->x1;
883         s->plane.y = box->y1;
884
885         /*
886          * Calculate the source & dest rects properly based on actual
887          * position (note the caller has called weston_surface_update_transform()
888          * for us already).
889          */
890         pixman_region32_init(&dest_rect);
891         pixman_region32_intersect(&dest_rect, &ev->transform.boundingbox,
892                                   &output_base->region);
893         pixman_region32_translate(&dest_rect, -output_base->x, -output_base->y);
894         box = pixman_region32_extents(&dest_rect);
895         tbox = weston_transformed_rect(output_base->width,
896                                        output_base->height,
897                                        output_base->transform,
898                                        output_base->current_scale,
899                                        *box);
900         s->dest_x = tbox.x1;
901         s->dest_y = tbox.y1;
902         s->dest_w = tbox.x2 - tbox.x1;
903         s->dest_h = tbox.y2 - tbox.y1;
904         pixman_region32_fini(&dest_rect);
905
906         pixman_region32_init(&src_rect);
907         pixman_region32_intersect(&src_rect, &ev->transform.boundingbox,
908                                   &output_base->region);
909         box = pixman_region32_extents(&src_rect);
910
911         weston_view_from_global_fixed(ev,
912                                       wl_fixed_from_int(box->x1),
913                                       wl_fixed_from_int(box->y1),
914                                       &sx1, &sy1);
915         weston_view_from_global_fixed(ev,
916                                       wl_fixed_from_int(box->x2),
917                                       wl_fixed_from_int(box->y2),
918                                       &sx2, &sy2);
919
920         if (sx1 < 0)
921                 sx1 = 0;
922         if (sy1 < 0)
923                 sy1 = 0;
924         if (sx2 > wl_fixed_from_int(ev->surface->width))
925                 sx2 = wl_fixed_from_int(ev->surface->width);
926         if (sy2 > wl_fixed_from_int(ev->surface->height))
927                 sy2 = wl_fixed_from_int(ev->surface->height);
928
929         tbox.x1 = sx1;
930         tbox.y1 = sy1;
931         tbox.x2 = sx2;
932         tbox.y2 = sy2;
933
934         tbox = weston_transformed_rect(wl_fixed_from_int(ev->surface->width),
935                                        wl_fixed_from_int(ev->surface->height),
936                                        ev->surface->buffer_viewport.transform,
937                                        ev->surface->buffer_viewport.scale,
938                                        tbox);
939
940         s->src_x = tbox.x1 << 8;
941         s->src_y = tbox.y1 << 8;
942         s->src_w = (tbox.x2 - tbox.x1) << 8;
943         s->src_h = (tbox.y2 - tbox.y1) << 8;
944         pixman_region32_fini(&src_rect);
945
946         return &s->plane;
947 }
948
949 static struct weston_plane *
950 drm_output_prepare_cursor_view(struct weston_output *output_base,
951                                struct weston_view *ev)
952 {
953         struct drm_compositor *c =
954                 (struct drm_compositor *) output_base->compositor;
955         struct drm_output *output = (struct drm_output *) output_base;
956
957         if (c->gbm == NULL)
958                 return NULL;
959         if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL)
960                 return NULL;
961         if (output->cursor_view)
962                 return NULL;
963         if (ev->output_mask != (1u << output_base->id))
964                 return NULL;
965         if (c->cursors_are_broken)
966                 return NULL;
967         if (ev->surface->buffer_ref.buffer == NULL ||
968             !wl_shm_buffer_get(ev->surface->buffer_ref.buffer->resource) ||
969             ev->surface->width > 64 || ev->surface->height > 64)
970                 return NULL;
971
972         output->cursor_view = ev;
973
974         return &output->cursor_plane;
975 }
976
977 static void
978 drm_output_set_cursor(struct drm_output *output)
979 {
980         struct weston_view *ev = output->cursor_view;
981         struct weston_buffer *buffer;
982         struct drm_compositor *c =
983                 (struct drm_compositor *) output->base.compositor;
984         EGLint handle, stride;
985         struct gbm_bo *bo;
986         uint32_t buf[64 * 64];
987         unsigned char *s;
988         int i, x, y;
989
990         output->cursor_view = NULL;
991         if (ev == NULL) {
992                 drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
993                 return;
994         }
995
996         buffer = ev->surface->buffer_ref.buffer;
997
998         if (buffer &&
999             pixman_region32_not_empty(&output->cursor_plane.damage)) {
1000                 pixman_region32_fini(&output->cursor_plane.damage);
1001                 pixman_region32_init(&output->cursor_plane.damage);
1002                 output->current_cursor ^= 1;
1003                 bo = output->cursor_bo[output->current_cursor];
1004                 memset(buf, 0, sizeof buf);
1005                 stride = wl_shm_buffer_get_stride(buffer->shm_buffer);
1006                 s = wl_shm_buffer_get_data(buffer->shm_buffer);
1007                 wl_shm_buffer_begin_access(buffer->shm_buffer);
1008                 for (i = 0; i < ev->surface->height; i++)
1009                         memcpy(buf + i * 64, s + i * stride,
1010                                ev->surface->width * 4);
1011                 wl_shm_buffer_end_access(buffer->shm_buffer);
1012
1013                 if (gbm_bo_write(bo, buf, sizeof buf) < 0)
1014                         weston_log("failed update cursor: %m\n");
1015
1016                 handle = gbm_bo_get_handle(bo).s32;
1017                 if (drmModeSetCursor(c->drm.fd,
1018                                      output->crtc_id, handle, 64, 64)) {
1019                         weston_log("failed to set cursor: %m\n");
1020                         c->cursors_are_broken = 1;
1021                 }
1022         }
1023
1024         x = (ev->geometry.x - output->base.x) * output->base.current_scale;
1025         y = (ev->geometry.y - output->base.y) * output->base.current_scale;
1026         if (output->cursor_plane.x != x || output->cursor_plane.y != y) {
1027                 if (drmModeMoveCursor(c->drm.fd, output->crtc_id, x, y)) {
1028                         weston_log("failed to move cursor: %m\n");
1029                         c->cursors_are_broken = 1;
1030                 }
1031
1032                 output->cursor_plane.x = x;
1033                 output->cursor_plane.y = y;
1034         }
1035 }
1036
1037 static void
1038 drm_assign_planes(struct weston_output *output)
1039 {
1040         struct drm_compositor *c =
1041                 (struct drm_compositor *) output->compositor;
1042         struct weston_view *ev, *next;
1043         pixman_region32_t overlap, surface_overlap;
1044         struct weston_plane *primary, *next_plane;
1045
1046         /*
1047          * Find a surface for each sprite in the output using some heuristics:
1048          * 1) size
1049          * 2) frequency of update
1050          * 3) opacity (though some hw might support alpha blending)
1051          * 4) clipping (this can be fixed with color keys)
1052          *
1053          * The idea is to save on blitting since this should save power.
1054          * If we can get a large video surface on the sprite for example,
1055          * the main display surface may not need to update at all, and
1056          * the client buffer can be used directly for the sprite surface
1057          * as we do for flipping full screen surfaces.
1058          */
1059         pixman_region32_init(&overlap);
1060         primary = &c->base.primary_plane;
1061
1062         wl_list_for_each_safe(ev, next, &c->base.view_list, link) {
1063                 struct weston_surface *es = ev->surface;
1064
1065                 /* Test whether this buffer can ever go into a plane:
1066                  * non-shm, or small enough to be a cursor.
1067                  *
1068                  * Also, keep a reference when using the pixman renderer.
1069                  * That makes it possible to do a seamless switch to the GL
1070                  * renderer and since the pixman renderer keeps a reference
1071                  * to the buffer anyway, there is no side effects.
1072                  */
1073                 if (c->use_pixman ||
1074                     (es->buffer_ref.buffer &&
1075                     (!wl_shm_buffer_get(es->buffer_ref.buffer->resource) ||
1076                      (ev->surface->width <= 64 && ev->surface->height <= 64))))
1077                         es->keep_buffer = 1;
1078                 else
1079                         es->keep_buffer = 0;
1080
1081                 pixman_region32_init(&surface_overlap);
1082                 pixman_region32_intersect(&surface_overlap, &overlap,
1083                                           &ev->transform.boundingbox);
1084
1085                 next_plane = NULL;
1086                 if (pixman_region32_not_empty(&surface_overlap))
1087                         next_plane = primary;
1088                 if (next_plane == NULL)
1089                         next_plane = drm_output_prepare_cursor_view(output, ev);
1090                 if (next_plane == NULL)
1091                         next_plane = drm_output_prepare_scanout_view(output, ev);
1092                 if (next_plane == NULL)
1093                         next_plane = drm_output_prepare_overlay_view(output, ev);
1094                 if (next_plane == NULL)
1095                         next_plane = primary;
1096                 weston_view_move_to_plane(ev, next_plane);
1097                 if (next_plane == primary)
1098                         pixman_region32_union(&overlap, &overlap,
1099                                               &ev->transform.boundingbox);
1100
1101                 pixman_region32_fini(&surface_overlap);
1102         }
1103         pixman_region32_fini(&overlap);
1104 }
1105
1106 static void
1107 drm_output_fini_pixman(struct drm_output *output);
1108
1109 static void
1110 drm_output_destroy(struct weston_output *output_base)
1111 {
1112         struct drm_output *output = (struct drm_output *) output_base;
1113         struct drm_compositor *c =
1114                 (struct drm_compositor *) output->base.compositor;
1115         drmModeCrtcPtr origcrtc = output->original_crtc;
1116
1117         if (output->page_flip_pending) {
1118                 output->destroy_pending = 1;
1119                 weston_log("destroy output while page flip pending\n");
1120                 return;
1121         }
1122
1123         if (output->backlight)
1124                 backlight_destroy(output->backlight);
1125
1126         drmModeFreeProperty(output->dpms_prop);
1127
1128         /* Turn off hardware cursor */
1129         drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
1130
1131         /* Restore original CRTC state */
1132         drmModeSetCrtc(c->drm.fd, origcrtc->crtc_id, origcrtc->buffer_id,
1133                        origcrtc->x, origcrtc->y,
1134                        &output->connector_id, 1, &origcrtc->mode);
1135         drmModeFreeCrtc(origcrtc);
1136
1137         c->crtc_allocator &= ~(1 << output->crtc_id);
1138         c->connector_allocator &= ~(1 << output->connector_id);
1139
1140         if (c->use_pixman) {
1141                 drm_output_fini_pixman(output);
1142         } else {
1143                 gl_renderer->output_destroy(output_base);
1144                 gbm_surface_destroy(output->surface);
1145         }
1146
1147         weston_plane_release(&output->fb_plane);
1148         weston_plane_release(&output->cursor_plane);
1149
1150         weston_output_destroy(&output->base);
1151
1152         free(output);
1153 }
1154
1155 static struct drm_mode *
1156 choose_mode (struct drm_output *output, struct weston_mode *target_mode)
1157 {
1158         struct drm_mode *tmp_mode = NULL, *mode;
1159
1160         if (output->base.current_mode->width == target_mode->width &&
1161             output->base.current_mode->height == target_mode->height &&
1162             (output->base.current_mode->refresh == target_mode->refresh ||
1163              target_mode->refresh == 0))
1164                 return (struct drm_mode *)output->base.current_mode;
1165
1166         wl_list_for_each(mode, &output->base.mode_list, base.link) {
1167                 if (mode->mode_info.hdisplay == target_mode->width &&
1168                     mode->mode_info.vdisplay == target_mode->height) {
1169                         if (mode->mode_info.vrefresh == target_mode->refresh || 
1170                             target_mode->refresh == 0) {
1171                                 return mode;
1172                         } else if (!tmp_mode) 
1173                                 tmp_mode = mode;
1174                 }
1175         }
1176
1177         return tmp_mode;
1178 }
1179
1180 static int
1181 drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec);
1182 static int
1183 drm_output_init_pixman(struct drm_output *output, struct drm_compositor *c);
1184
1185 static int
1186 drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mode)
1187 {
1188         struct drm_output *output;
1189         struct drm_mode *drm_mode;
1190         struct drm_compositor *ec;
1191
1192         if (output_base == NULL) {
1193                 weston_log("output is NULL.\n");
1194                 return -1;
1195         }
1196
1197         if (mode == NULL) {
1198                 weston_log("mode is NULL.\n");
1199                 return -1;
1200         }
1201
1202         ec = (struct drm_compositor *)output_base->compositor;
1203         output = (struct drm_output *)output_base;
1204         drm_mode  = choose_mode (output, mode);
1205
1206         if (!drm_mode) {
1207                 weston_log("%s, invalid resolution:%dx%d\n", __func__, mode->width, mode->height);
1208                 return -1;
1209         }
1210
1211         if (&drm_mode->base == output->base.current_mode)
1212                 return 0;
1213
1214         output->base.current_mode->flags = 0;
1215
1216         output->base.current_mode = &drm_mode->base;
1217         output->base.current_mode->flags =
1218                 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
1219
1220         /* reset rendering stuff. */
1221         drm_output_release_fb(output, output->current);
1222         drm_output_release_fb(output, output->next);
1223         output->current = output->next = NULL;
1224
1225         if (ec->use_pixman) {
1226                 drm_output_fini_pixman(output);
1227                 if (drm_output_init_pixman(output, ec) < 0) {
1228                         weston_log("failed to init output pixman state with "
1229                                    "new mode\n");
1230                         return -1;
1231                 }
1232         } else {
1233                 gl_renderer->output_destroy(&output->base);
1234                 gbm_surface_destroy(output->surface);
1235
1236                 if (drm_output_init_egl(output, ec) < 0) {
1237                         weston_log("failed to init output egl state with "
1238                                    "new mode");
1239                         return -1;
1240                 }
1241         }
1242
1243         return 0;
1244 }
1245
1246 static int
1247 on_drm_input(int fd, uint32_t mask, void *data)
1248 {
1249         drmEventContext evctx;
1250
1251         memset(&evctx, 0, sizeof evctx);
1252         evctx.version = DRM_EVENT_CONTEXT_VERSION;
1253         evctx.page_flip_handler = page_flip_handler;
1254         evctx.vblank_handler = vblank_handler;
1255         drmHandleEvent(fd, &evctx);
1256
1257         return 1;
1258 }
1259
1260 static int
1261 init_drm(struct drm_compositor *ec, struct udev_device *device)
1262 {
1263         const char *filename, *sysnum;
1264         uint64_t cap;
1265         int fd, ret;
1266
1267         sysnum = udev_device_get_sysnum(device);
1268         if (sysnum)
1269                 ec->drm.id = atoi(sysnum);
1270         if (!sysnum || ec->drm.id < 0) {
1271                 weston_log("cannot get device sysnum\n");
1272                 return -1;
1273         }
1274
1275         filename = udev_device_get_devnode(device);
1276         fd = weston_launcher_open(ec->base.launcher, filename, O_RDWR);
1277         if (fd < 0) {
1278                 /* Probably permissions error */
1279                 weston_log("couldn't open %s, skipping\n",
1280                         udev_device_get_devnode(device));
1281                 return -1;
1282         }
1283
1284         weston_log("using %s\n", filename);
1285
1286         ec->drm.fd = fd;
1287         ec->drm.filename = strdup(filename);
1288
1289         ret = drmGetCap(fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap);
1290         if (ret == 0 && cap == 1)
1291                 ec->clock = CLOCK_MONOTONIC;
1292         else
1293                 ec->clock = CLOCK_REALTIME;
1294
1295         return 0;
1296 }
1297
1298 static struct gbm_device *
1299 create_gbm_device(int fd)
1300 {
1301         struct gbm_device *gbm;
1302
1303         gl_renderer = weston_load_module("gl-renderer.so",
1304                                          "gl_renderer_interface");
1305         if (!gl_renderer)
1306                 return NULL;
1307
1308         /* GBM will load a dri driver, but even though they need symbols from
1309          * libglapi, in some version of Mesa they are not linked to it. Since
1310          * only the gl-renderer module links to it, the call above won't make
1311          * these symbols globally available, and loading the DRI driver fails.
1312          * Workaround this by dlopen()'ing libglapi with RTLD_GLOBAL. */
1313         dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL);
1314
1315         gbm = gbm_create_device(fd);
1316
1317         return gbm;
1318 }
1319
1320 static int
1321 drm_compositor_create_gl_renderer(struct drm_compositor *ec)
1322 {
1323         EGLint format;
1324
1325         format = ec->format;
1326         if (gl_renderer->create(&ec->base, ec->gbm,
1327                                gl_renderer->opaque_attribs, &format) < 0) {
1328                 return -1;
1329         }
1330
1331         return 0;
1332 }
1333
1334 static int
1335 init_egl(struct drm_compositor *ec)
1336 {
1337         ec->gbm = create_gbm_device(ec->drm.fd);
1338
1339         if (!ec->gbm)
1340                 return -1;
1341
1342         if (drm_compositor_create_gl_renderer(ec) < 0) {
1343                 gbm_device_destroy(ec->gbm);
1344                 return -1;
1345         }
1346
1347         return 0;
1348 }
1349
1350 static int
1351 init_pixman(struct drm_compositor *ec)
1352 {
1353         return pixman_renderer_init(&ec->base);
1354 }
1355
1356 static struct drm_mode *
1357 drm_output_add_mode(struct drm_output *output, drmModeModeInfo *info)
1358 {
1359         struct drm_mode *mode;
1360         uint64_t refresh;
1361
1362         mode = malloc(sizeof *mode);
1363         if (mode == NULL)
1364                 return NULL;
1365
1366         mode->base.flags = 0;
1367         mode->base.width = info->hdisplay;
1368         mode->base.height = info->vdisplay;
1369
1370         /* Calculate higher precision (mHz) refresh rate */
1371         refresh = (info->clock * 1000000LL / info->htotal +
1372                    info->vtotal / 2) / info->vtotal;
1373
1374         if (info->flags & DRM_MODE_FLAG_INTERLACE)
1375                 refresh *= 2;
1376         if (info->flags & DRM_MODE_FLAG_DBLSCAN)
1377                 refresh /= 2;
1378         if (info->vscan > 1)
1379             refresh /= info->vscan;
1380
1381         mode->base.refresh = refresh;
1382         mode->mode_info = *info;
1383
1384         if (info->type & DRM_MODE_TYPE_PREFERRED)
1385                 mode->base.flags |= WL_OUTPUT_MODE_PREFERRED;
1386
1387         wl_list_insert(output->base.mode_list.prev, &mode->base.link);
1388
1389         return mode;
1390 }
1391
1392 static int
1393 drm_subpixel_to_wayland(int drm_value)
1394 {
1395         switch (drm_value) {
1396         default:
1397         case DRM_MODE_SUBPIXEL_UNKNOWN:
1398                 return WL_OUTPUT_SUBPIXEL_UNKNOWN;
1399         case DRM_MODE_SUBPIXEL_NONE:
1400                 return WL_OUTPUT_SUBPIXEL_NONE;
1401         case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
1402                 return WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB;
1403         case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
1404                 return WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR;
1405         case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
1406                 return WL_OUTPUT_SUBPIXEL_VERTICAL_RGB;
1407         case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
1408                 return WL_OUTPUT_SUBPIXEL_VERTICAL_BGR;
1409         }
1410 }
1411
1412 /* returns a value between 0-255 range, where higher is brighter */
1413 static uint32_t
1414 drm_get_backlight(struct drm_output *output)
1415 {
1416         long brightness, max_brightness, norm;
1417
1418         brightness = backlight_get_brightness(output->backlight);
1419         max_brightness = backlight_get_max_brightness(output->backlight);
1420
1421         /* convert it on a scale of 0 to 255 */
1422         norm = (brightness * 255)/(max_brightness);
1423
1424         return (uint32_t) norm;
1425 }
1426
1427 /* values accepted are between 0-255 range */
1428 static void
1429 drm_set_backlight(struct weston_output *output_base, uint32_t value)
1430 {
1431         struct drm_output *output = (struct drm_output *) output_base;
1432         long max_brightness, new_brightness;
1433
1434         if (!output->backlight)
1435                 return;
1436
1437         if (value > 255)
1438                 return;
1439
1440         max_brightness = backlight_get_max_brightness(output->backlight);
1441
1442         /* get denormalized value */
1443         new_brightness = (value * max_brightness) / 255;
1444
1445         backlight_set_brightness(output->backlight, new_brightness);
1446 }
1447
1448 static drmModePropertyPtr
1449 drm_get_prop(int fd, drmModeConnectorPtr connector, const char *name)
1450 {
1451         drmModePropertyPtr props;
1452         int i;
1453
1454         for (i = 0; i < connector->count_props; i++) {
1455                 props = drmModeGetProperty(fd, connector->props[i]);
1456                 if (!props)
1457                         continue;
1458
1459                 if (!strcmp(props->name, name))
1460                         return props;
1461
1462                 drmModeFreeProperty(props);
1463         }
1464
1465         return NULL;
1466 }
1467
1468 static void
1469 drm_set_dpms(struct weston_output *output_base, enum dpms_enum level)
1470 {
1471         struct drm_output *output = (struct drm_output *) output_base;
1472         struct weston_compositor *ec = output_base->compositor;
1473         struct drm_compositor *c = (struct drm_compositor *) ec;
1474
1475         if (!output->dpms_prop)
1476                 return;
1477
1478         drmModeConnectorSetProperty(c->drm.fd, output->connector_id,
1479                                     output->dpms_prop->prop_id, level);
1480 }
1481
1482 static const char *connector_type_names[] = {
1483         "None",
1484         "VGA",
1485         "DVI",
1486         "DVI",
1487         "DVI",
1488         "Composite",
1489         "TV",
1490         "LVDS",
1491         "CTV",
1492         "DIN",
1493         "DP",
1494         "HDMI",
1495         "HDMI",
1496         "TV",
1497         "eDP",
1498 };
1499
1500 static int
1501 find_crtc_for_connector(struct drm_compositor *ec,
1502                         drmModeRes *resources, drmModeConnector *connector)
1503 {
1504         drmModeEncoder *encoder;
1505         uint32_t possible_crtcs;
1506         int i, j;
1507
1508         for (j = 0; j < connector->count_encoders; j++) {
1509                 encoder = drmModeGetEncoder(ec->drm.fd, connector->encoders[j]);
1510                 if (encoder == NULL) {
1511                         weston_log("Failed to get encoder.\n");
1512                         return -1;
1513                 }
1514                 possible_crtcs = encoder->possible_crtcs;
1515                 drmModeFreeEncoder(encoder);
1516
1517                 for (i = 0; i < resources->count_crtcs; i++) {
1518                         if (possible_crtcs & (1 << i) &&
1519                             !(ec->crtc_allocator & (1 << resources->crtcs[i])))
1520                                 return i;
1521                 }
1522         }
1523
1524         return -1;
1525 }
1526
1527 /* Init output state that depends on gl or gbm */
1528 static int
1529 drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec)
1530 {
1531         int i, flags;
1532
1533         output->surface = gbm_surface_create(ec->gbm,
1534                                              output->base.current_mode->width,
1535                                              output->base.current_mode->height,
1536                                              ec->format,
1537                                              GBM_BO_USE_SCANOUT |
1538                                              GBM_BO_USE_RENDERING);
1539         if (!output->surface) {
1540                 weston_log("failed to create gbm surface\n");
1541                 return -1;
1542         }
1543
1544         if (gl_renderer->output_create(&output->base, output->surface) < 0) {
1545                 weston_log("failed to create gl renderer output state\n");
1546                 gbm_surface_destroy(output->surface);
1547                 return -1;
1548         }
1549
1550         flags = GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE;
1551
1552         for (i = 0; i < 2; i++) {
1553                 if (output->cursor_bo[i])
1554                         continue;
1555
1556                 output->cursor_bo[i] =
1557                         gbm_bo_create(ec->gbm, 64, 64, GBM_FORMAT_ARGB8888,
1558                                       flags);
1559         }
1560
1561         if (output->cursor_bo[0] == NULL || output->cursor_bo[1] == NULL) {
1562                 weston_log("cursor buffers unavailable, using gl cursors\n");
1563                 ec->cursors_are_broken = 1;
1564         }
1565
1566         return 0;
1567 }
1568
1569 static int
1570 drm_output_init_pixman(struct drm_output *output, struct drm_compositor *c)
1571 {
1572         int w = output->base.current_mode->width;
1573         int h = output->base.current_mode->height;
1574         unsigned int i;
1575
1576         /* FIXME error checking */
1577
1578         for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
1579                 output->dumb[i] = drm_fb_create_dumb(c, w, h);
1580                 if (!output->dumb[i])
1581                         goto err;
1582
1583                 output->image[i] =
1584                         pixman_image_create_bits(PIXMAN_x8r8g8b8, w, h,
1585                                                  output->dumb[i]->map,
1586                                                  output->dumb[i]->stride);
1587                 if (!output->image[i])
1588                         goto err;
1589         }
1590
1591         if (pixman_renderer_output_create(&output->base) < 0)
1592                 goto err;
1593
1594         pixman_region32_init_rect(&output->previous_damage,
1595                                   output->base.x, output->base.y, output->base.width, output->base.height);
1596
1597         return 0;
1598
1599 err:
1600         for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
1601                 if (output->dumb[i])
1602                         drm_fb_destroy_dumb(output->dumb[i]);
1603                 if (output->image[i])
1604                         pixman_image_unref(output->image[i]);
1605
1606                 output->dumb[i] = NULL;
1607                 output->image[i] = NULL;
1608         }
1609
1610         return -1;
1611 }
1612
1613 static void
1614 drm_output_fini_pixman(struct drm_output *output)
1615 {
1616         unsigned int i;
1617
1618         pixman_renderer_output_destroy(&output->base);
1619         pixman_region32_fini(&output->previous_damage);
1620
1621         for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
1622                 drm_fb_destroy_dumb(output->dumb[i]);
1623                 pixman_image_unref(output->image[i]);
1624                 output->dumb[i] = NULL;
1625                 output->image[i] = NULL;
1626         }
1627 }
1628
1629 static void
1630 edid_parse_string(const uint8_t *data, char text[])
1631 {
1632         int i;
1633         int replaced = 0;
1634
1635         /* this is always 12 bytes, but we can't guarantee it's null
1636          * terminated or not junk. */
1637         strncpy(text, (const char *) data, 12);
1638
1639         /* remove insane chars */
1640         for (i = 0; text[i] != '\0'; i++) {
1641                 if (text[i] == '\n' ||
1642                     text[i] == '\r') {
1643                         text[i] = '\0';
1644                         break;
1645                 }
1646         }
1647
1648         /* ensure string is printable */
1649         for (i = 0; text[i] != '\0'; i++) {
1650                 if (!isprint(text[i])) {
1651                         text[i] = '-';
1652                         replaced++;
1653                 }
1654         }
1655
1656         /* if the string is random junk, ignore the string */
1657         if (replaced > 4)
1658                 text[0] = '\0';
1659 }
1660
1661 #define EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING        0xfe
1662 #define EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME            0xfc
1663 #define EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER   0xff
1664 #define EDID_OFFSET_DATA_BLOCKS                         0x36
1665 #define EDID_OFFSET_LAST_BLOCK                          0x6c
1666 #define EDID_OFFSET_PNPID                               0x08
1667 #define EDID_OFFSET_SERIAL                              0x0c
1668
1669 static int
1670 edid_parse(struct drm_edid *edid, const uint8_t *data, size_t length)
1671 {
1672         int i;
1673         uint32_t serial_number;
1674
1675         /* check header */
1676         if (length < 128)
1677                 return -1;
1678         if (data[0] != 0x00 || data[1] != 0xff)
1679                 return -1;
1680
1681         /* decode the PNP ID from three 5 bit words packed into 2 bytes
1682          * /--08--\/--09--\
1683          * 7654321076543210
1684          * |\---/\---/\---/
1685          * R  C1   C2   C3 */
1686         edid->pnp_id[0] = 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x7c) / 4) - 1;
1687         edid->pnp_id[1] = 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x3) * 8) + ((data[EDID_OFFSET_PNPID + 1] & 0xe0) / 32) - 1;
1688         edid->pnp_id[2] = 'A' + (data[EDID_OFFSET_PNPID + 1] & 0x1f) - 1;
1689         edid->pnp_id[3] = '\0';
1690
1691         /* maybe there isn't a ASCII serial number descriptor, so use this instead */
1692         serial_number = (uint32_t) data[EDID_OFFSET_SERIAL + 0];
1693         serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 1] * 0x100;
1694         serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 2] * 0x10000;
1695         serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 3] * 0x1000000;
1696         if (serial_number > 0)
1697                 sprintf(edid->serial_number, "%lu", (unsigned long) serial_number);
1698
1699         /* parse EDID data */
1700         for (i = EDID_OFFSET_DATA_BLOCKS;
1701              i <= EDID_OFFSET_LAST_BLOCK;
1702              i += 18) {
1703                 /* ignore pixel clock data */
1704                 if (data[i] != 0)
1705                         continue;
1706                 if (data[i+2] != 0)
1707                         continue;
1708
1709                 /* any useful blocks? */
1710                 if (data[i+3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME) {
1711                         edid_parse_string(&data[i+5],
1712                                           edid->monitor_name);
1713                 } else if (data[i+3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER) {
1714                         edid_parse_string(&data[i+5],
1715                                           edid->serial_number);
1716                 } else if (data[i+3] == EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING) {
1717                         edid_parse_string(&data[i+5],
1718                                           edid->eisa_id);
1719                 }
1720         }
1721         return 0;
1722 }
1723
1724 static void
1725 find_and_parse_output_edid(struct drm_compositor *ec,
1726                            struct drm_output *output,
1727                            drmModeConnector *connector)
1728 {
1729         drmModePropertyBlobPtr edid_blob = NULL;
1730         drmModePropertyPtr property;
1731         int i;
1732         int rc;
1733
1734         for (i = 0; i < connector->count_props && !edid_blob; i++) {
1735                 property = drmModeGetProperty(ec->drm.fd, connector->props[i]);
1736                 if (!property)
1737                         continue;
1738                 if ((property->flags & DRM_MODE_PROP_BLOB) &&
1739                     !strcmp(property->name, "EDID")) {
1740                         edid_blob = drmModeGetPropertyBlob(ec->drm.fd,
1741                                                            connector->prop_values[i]);
1742                 }
1743                 drmModeFreeProperty(property);
1744         }
1745         if (!edid_blob)
1746                 return;
1747
1748         rc = edid_parse(&output->edid,
1749                         edid_blob->data,
1750                         edid_blob->length);
1751         if (!rc) {
1752                 weston_log("EDID data '%s', '%s', '%s'\n",
1753                            output->edid.pnp_id,
1754                            output->edid.monitor_name,
1755                            output->edid.serial_number);
1756                 if (output->edid.pnp_id[0] != '\0')
1757                         output->base.make = output->edid.pnp_id;
1758                 if (output->edid.monitor_name[0] != '\0')
1759                         output->base.model = output->edid.monitor_name;
1760                 if (output->edid.serial_number[0] != '\0')
1761                         output->base.serial_number = output->edid.serial_number;
1762         }
1763         drmModeFreePropertyBlob(edid_blob);
1764 }
1765
1766
1767
1768 static int
1769 parse_modeline(const char *s, drmModeModeInfo *mode)
1770 {
1771         char hsync[16];
1772         char vsync[16];
1773         float fclock;
1774
1775         mode->type = DRM_MODE_TYPE_USERDEF;
1776         mode->hskew = 0;
1777         mode->vscan = 0;
1778         mode->vrefresh = 0;
1779         mode->flags = 0;
1780
1781         if (sscanf(s, "%f %hd %hd %hd %hd %hd %hd %hd %hd %15s %15s",
1782                    &fclock,
1783                    &mode->hdisplay,
1784                    &mode->hsync_start,
1785                    &mode->hsync_end,
1786                    &mode->htotal,
1787                    &mode->vdisplay,
1788                    &mode->vsync_start,
1789                    &mode->vsync_end,
1790                    &mode->vtotal, hsync, vsync) != 11)
1791                 return -1;
1792
1793         mode->clock = fclock * 1000;
1794         if (strcmp(hsync, "+hsync") == 0)
1795                 mode->flags |= DRM_MODE_FLAG_PHSYNC;
1796         else if (strcmp(hsync, "-hsync") == 0)
1797                 mode->flags |= DRM_MODE_FLAG_NHSYNC;
1798         else
1799                 return -1;
1800
1801         if (strcmp(vsync, "+vsync") == 0)
1802                 mode->flags |= DRM_MODE_FLAG_PVSYNC;
1803         else if (strcmp(vsync, "-vsync") == 0)
1804                 mode->flags |= DRM_MODE_FLAG_NVSYNC;
1805         else
1806                 return -1;
1807
1808         return 0;
1809 }
1810
1811 static uint32_t
1812 parse_transform(const char *transform, const char *output_name)
1813 {
1814         static const struct { const char *name; uint32_t token; } names[] = {
1815                 { "normal",     WL_OUTPUT_TRANSFORM_NORMAL },
1816                 { "90",         WL_OUTPUT_TRANSFORM_90 },
1817                 { "180",        WL_OUTPUT_TRANSFORM_180 },
1818                 { "270",        WL_OUTPUT_TRANSFORM_270 },
1819                 { "flipped",    WL_OUTPUT_TRANSFORM_FLIPPED },
1820                 { "flipped-90", WL_OUTPUT_TRANSFORM_FLIPPED_90 },
1821                 { "flipped-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 },
1822                 { "flipped-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 },
1823         };
1824         unsigned int i;
1825
1826         for (i = 0; i < ARRAY_LENGTH(names); i++)
1827                 if (strcmp(names[i].name, transform) == 0)
1828                         return names[i].token;
1829
1830         weston_log("Invalid transform \"%s\" for output %s\n",
1831                    transform, output_name);
1832
1833         return WL_OUTPUT_TRANSFORM_NORMAL;
1834 }
1835
1836 static void
1837 setup_output_seat_constraint(struct drm_compositor *ec,
1838                              struct weston_output *output,
1839                              const char *s)
1840 {
1841         if (strcmp(s, "") != 0) {
1842                 struct udev_seat *seat;
1843
1844                 seat = udev_seat_get_named(&ec->base, s);
1845                 if (seat)
1846                         seat->base.output = output;
1847
1848                 if (seat && seat->base.pointer)
1849                         weston_pointer_clamp(seat->base.pointer,
1850                                              &seat->base.pointer->x,
1851                                              &seat->base.pointer->y);
1852         }
1853 }
1854
1855 static int
1856 create_output_for_connector(struct drm_compositor *ec,
1857                             drmModeRes *resources,
1858                             drmModeConnector *connector,
1859                             int x, int y, struct udev_device *drm_device)
1860 {
1861         struct drm_output *output;
1862         struct drm_mode *drm_mode, *next, *preferred, *current, *configured, *best;
1863         struct weston_mode *m;
1864         struct weston_config_section *section;
1865         drmModeEncoder *encoder;
1866         drmModeModeInfo crtc_mode, modeline;
1867         drmModeCrtc *crtc;
1868         int i, width, height, scale;
1869         char name[32], *s;
1870         const char *type_name;
1871         enum output_config config;
1872         uint32_t transform;
1873
1874         i = find_crtc_for_connector(ec, resources, connector);
1875         if (i < 0) {
1876                 weston_log("No usable crtc/encoder pair for connector.\n");
1877                 return -1;
1878         }
1879
1880         output = zalloc(sizeof *output);
1881         if (output == NULL)
1882                 return -1;
1883
1884         output->base.subpixel = drm_subpixel_to_wayland(connector->subpixel);
1885         output->base.make = "unknown";
1886         output->base.model = "unknown";
1887         output->base.serial_number = "unknown";
1888         wl_list_init(&output->base.mode_list);
1889
1890         if (connector->connector_type < ARRAY_LENGTH(connector_type_names))
1891                 type_name = connector_type_names[connector->connector_type];
1892         else
1893                 type_name = "UNKNOWN";
1894         snprintf(name, 32, "%s%d", type_name, connector->connector_type_id);
1895         output->base.name = strdup(name);
1896
1897         section = weston_config_get_section(ec->base.config, "output", "name",
1898                                             output->base.name);
1899         weston_config_section_get_string(section, "mode", &s, "preferred");
1900         if (strcmp(s, "off") == 0)
1901                 config = OUTPUT_CONFIG_OFF;
1902         else if (strcmp(s, "preferred") == 0)
1903                 config = OUTPUT_CONFIG_PREFERRED;
1904         else if (strcmp(s, "current") == 0)
1905                 config = OUTPUT_CONFIG_CURRENT;
1906         else if (sscanf(s, "%dx%d", &width, &height) == 2)
1907                 config = OUTPUT_CONFIG_MODE;
1908         else if (parse_modeline(s, &modeline) == 0)
1909                 config = OUTPUT_CONFIG_MODELINE;
1910         else {
1911                 weston_log("Invalid mode \"%s\" for output %s\n",
1912                            s, output->base.name);
1913                 config = OUTPUT_CONFIG_PREFERRED;
1914         }
1915         free(s);
1916
1917         weston_config_section_get_int(section, "scale", &scale, 1);
1918         weston_config_section_get_string(section, "transform", &s, "normal");
1919         transform = parse_transform(s, output->base.name);
1920         free(s);
1921
1922         weston_config_section_get_string(section, "seat", &s, "");
1923         setup_output_seat_constraint(ec, &output->base, s);
1924         free(s);
1925
1926         output->crtc_id = resources->crtcs[i];
1927         output->pipe = i;
1928         ec->crtc_allocator |= (1 << output->crtc_id);
1929         output->connector_id = connector->connector_id;
1930         ec->connector_allocator |= (1 << output->connector_id);
1931
1932         output->original_crtc = drmModeGetCrtc(ec->drm.fd, output->crtc_id);
1933         output->dpms_prop = drm_get_prop(ec->drm.fd, connector, "DPMS");
1934
1935         /* Get the current mode on the crtc that's currently driving
1936          * this connector. */
1937         encoder = drmModeGetEncoder(ec->drm.fd, connector->encoder_id);
1938         memset(&crtc_mode, 0, sizeof crtc_mode);
1939         if (encoder != NULL) {
1940                 crtc = drmModeGetCrtc(ec->drm.fd, encoder->crtc_id);
1941                 drmModeFreeEncoder(encoder);
1942                 if (crtc == NULL)
1943                         goto err_free;
1944                 if (crtc->mode_valid)
1945                         crtc_mode = crtc->mode;
1946                 drmModeFreeCrtc(crtc);
1947         }
1948
1949         for (i = 0; i < connector->count_modes; i++) {
1950                 drm_mode = drm_output_add_mode(output, &connector->modes[i]);
1951                 if (!drm_mode)
1952                         goto err_free;
1953         }
1954
1955         if (config == OUTPUT_CONFIG_OFF) {
1956                 weston_log("Disabling output %s\n", output->base.name);
1957                 drmModeSetCrtc(ec->drm.fd, output->crtc_id,
1958                                0, 0, 0, 0, 0, NULL);
1959                 goto err_free;
1960         }
1961
1962         preferred = NULL;
1963         current = NULL;
1964         configured = NULL;
1965         best = NULL;
1966
1967         wl_list_for_each_reverse(drm_mode, &output->base.mode_list, base.link) {
1968                 if (config == OUTPUT_CONFIG_MODE &&
1969                     width == drm_mode->base.width &&
1970                     height == drm_mode->base.height)
1971                         configured = drm_mode;
1972                 if (!memcmp(&crtc_mode, &drm_mode->mode_info, sizeof crtc_mode))
1973                         current = drm_mode;
1974                 if (drm_mode->base.flags & WL_OUTPUT_MODE_PREFERRED)
1975                         preferred = drm_mode;
1976                 best = drm_mode;
1977         }
1978
1979         if (config == OUTPUT_CONFIG_MODELINE) {
1980                 configured = drm_output_add_mode(output, &modeline);
1981                 if (!configured)
1982                         goto err_free;
1983         }
1984
1985         if (current == NULL && crtc_mode.clock != 0) {
1986                 current = drm_output_add_mode(output, &crtc_mode);
1987                 if (!current)
1988                         goto err_free;
1989         }
1990
1991         if (config == OUTPUT_CONFIG_CURRENT)
1992                 configured = current;
1993
1994         if (option_current_mode && current)
1995                 output->base.current_mode = &current->base;
1996         else if (configured)
1997                 output->base.current_mode = &configured->base;
1998         else if (preferred)
1999                 output->base.current_mode = &preferred->base;
2000         else if (current)
2001                 output->base.current_mode = &current->base;
2002         else if (best)
2003                 output->base.current_mode = &best->base;
2004
2005         if (output->base.current_mode == NULL) {
2006                 weston_log("no available modes for %s\n", output->base.name);
2007                 goto err_free;
2008         }
2009
2010         output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
2011
2012         weston_output_init(&output->base, &ec->base, x, y,
2013                            connector->mmWidth, connector->mmHeight,
2014                            transform, scale);
2015
2016         if (ec->use_pixman) {
2017                 if (drm_output_init_pixman(output, ec) < 0) {
2018                         weston_log("Failed to init output pixman state\n");
2019                         goto err_output;
2020                 }
2021         } else if (drm_output_init_egl(output, ec) < 0) {
2022                 weston_log("Failed to init output gl state\n");
2023                 goto err_output;
2024         }
2025
2026         output->backlight = backlight_init(drm_device,
2027                                            connector->connector_type);
2028         if (output->backlight) {
2029                 weston_log("Initialized backlight, device %s\n",
2030                            output->backlight->path);
2031                 output->base.set_backlight = drm_set_backlight;
2032                 output->base.backlight_current = drm_get_backlight(output);
2033         } else {
2034                 weston_log("Failed to initialize backlight\n");
2035         }
2036
2037         wl_list_insert(ec->base.output_list.prev, &output->base.link);
2038
2039         find_and_parse_output_edid(ec, output, connector);
2040         if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
2041                 output->base.connection_internal = 1;
2042
2043         output->base.start_repaint_loop = drm_output_start_repaint_loop;
2044         output->base.repaint = drm_output_repaint;
2045         output->base.destroy = drm_output_destroy;
2046         output->base.assign_planes = drm_assign_planes;
2047         output->base.set_dpms = drm_set_dpms;
2048         output->base.switch_mode = drm_output_switch_mode;
2049
2050         output->base.gamma_size = output->original_crtc->gamma_size;
2051         output->base.set_gamma = drm_output_set_gamma;
2052
2053         weston_plane_init(&output->cursor_plane, &ec->base, 0, 0);
2054         weston_plane_init(&output->fb_plane, &ec->base, 0, 0);
2055
2056         weston_compositor_stack_plane(&ec->base, &output->cursor_plane, NULL);
2057         weston_compositor_stack_plane(&ec->base, &output->fb_plane,
2058                                       &ec->base.primary_plane);
2059
2060         weston_log("Output %s, (connector %d, crtc %d)\n",
2061                    output->base.name, output->connector_id, output->crtc_id);
2062         wl_list_for_each(m, &output->base.mode_list, link)
2063                 weston_log_continue(STAMP_SPACE "mode %dx%d@%.1f%s%s%s\n",
2064                                     m->width, m->height, m->refresh / 1000.0,
2065                                     m->flags & WL_OUTPUT_MODE_PREFERRED ?
2066                                     ", preferred" : "",
2067                                     m->flags & WL_OUTPUT_MODE_CURRENT ?
2068                                     ", current" : "",
2069                                     connector->count_modes == 0 ?
2070                                     ", built-in" : "");
2071
2072         return 0;
2073
2074 err_output:
2075         weston_output_destroy(&output->base);
2076 err_free:
2077         wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
2078                                                         base.link) {
2079                 wl_list_remove(&drm_mode->base.link);
2080                 free(drm_mode);
2081         }
2082
2083         drmModeFreeCrtc(output->original_crtc);
2084         ec->crtc_allocator &= ~(1 << output->crtc_id);
2085         ec->connector_allocator &= ~(1 << output->connector_id);
2086         free(output);
2087
2088         return -1;
2089 }
2090
2091 static void
2092 create_sprites(struct drm_compositor *ec)
2093 {
2094         struct drm_sprite *sprite;
2095         drmModePlaneRes *plane_res;
2096         drmModePlane *plane;
2097         uint32_t i;
2098
2099         plane_res = drmModeGetPlaneResources(ec->drm.fd);
2100         if (!plane_res) {
2101                 weston_log("failed to get plane resources: %s\n",
2102                         strerror(errno));
2103                 return;
2104         }
2105
2106         for (i = 0; i < plane_res->count_planes; i++) {
2107                 plane = drmModeGetPlane(ec->drm.fd, plane_res->planes[i]);
2108                 if (!plane)
2109                         continue;
2110
2111                 sprite = zalloc(sizeof(*sprite) + ((sizeof(uint32_t)) *
2112                                                    plane->count_formats));
2113                 if (!sprite) {
2114                         weston_log("%s: out of memory\n",
2115                                 __func__);
2116                         drmModeFreePlane(plane);
2117                         continue;
2118                 }
2119
2120                 sprite->possible_crtcs = plane->possible_crtcs;
2121                 sprite->plane_id = plane->plane_id;
2122                 sprite->current = NULL;
2123                 sprite->next = NULL;
2124                 sprite->compositor = ec;
2125                 sprite->count_formats = plane->count_formats;
2126                 memcpy(sprite->formats, plane->formats,
2127                        plane->count_formats * sizeof(plane->formats[0]));
2128                 drmModeFreePlane(plane);
2129                 weston_plane_init(&sprite->plane, &ec->base, 0, 0);
2130                 weston_compositor_stack_plane(&ec->base, &sprite->plane,
2131                                               &ec->base.primary_plane);
2132
2133                 wl_list_insert(&ec->sprite_list, &sprite->link);
2134         }
2135
2136         drmModeFreePlaneResources(plane_res);
2137 }
2138
2139 static void
2140 destroy_sprites(struct drm_compositor *compositor)
2141 {
2142         struct drm_sprite *sprite, *next;
2143         struct drm_output *output;
2144
2145         output = container_of(compositor->base.output_list.next,
2146                               struct drm_output, base.link);
2147
2148         wl_list_for_each_safe(sprite, next, &compositor->sprite_list, link) {
2149                 drmModeSetPlane(compositor->drm.fd,
2150                                 sprite->plane_id,
2151                                 output->crtc_id, 0, 0,
2152                                 0, 0, 0, 0, 0, 0, 0, 0);
2153                 drm_output_release_fb(output, sprite->current);
2154                 drm_output_release_fb(output, sprite->next);
2155                 weston_plane_release(&sprite->plane);
2156                 free(sprite);
2157         }
2158 }
2159
2160 static int
2161 create_outputs(struct drm_compositor *ec, uint32_t option_connector,
2162                struct udev_device *drm_device)
2163 {
2164         drmModeConnector *connector;
2165         drmModeRes *resources;
2166         int i;
2167         int x = 0, y = 0;
2168
2169         resources = drmModeGetResources(ec->drm.fd);
2170         if (!resources) {
2171                 weston_log("drmModeGetResources failed\n");
2172                 return -1;
2173         }
2174
2175         ec->crtcs = calloc(resources->count_crtcs, sizeof(uint32_t));
2176         if (!ec->crtcs) {
2177                 drmModeFreeResources(resources);
2178                 return -1;
2179         }
2180
2181         ec->min_width  = resources->min_width;
2182         ec->max_width  = resources->max_width;
2183         ec->min_height = resources->min_height;
2184         ec->max_height = resources->max_height;
2185
2186         ec->num_crtcs = resources->count_crtcs;
2187         memcpy(ec->crtcs, resources->crtcs, sizeof(uint32_t) * ec->num_crtcs);
2188
2189         for (i = 0; i < resources->count_connectors; i++) {
2190                 connector = drmModeGetConnector(ec->drm.fd,
2191                                                 resources->connectors[i]);
2192                 if (connector == NULL)
2193                         continue;
2194
2195                 if (connector->connection == DRM_MODE_CONNECTED &&
2196                     (option_connector == 0 ||
2197                      connector->connector_id == option_connector)) {
2198                         if (create_output_for_connector(ec, resources,
2199                                                         connector, x, y,
2200                                                         drm_device) < 0) {
2201                                 drmModeFreeConnector(connector);
2202                                 continue;
2203                         }
2204
2205                         x += container_of(ec->base.output_list.prev,
2206                                           struct weston_output,
2207                                           link)->width;
2208                 }
2209
2210                 drmModeFreeConnector(connector);
2211         }
2212
2213         if (wl_list_empty(&ec->base.output_list)) {
2214                 weston_log("No currently active connector found.\n");
2215                 drmModeFreeResources(resources);
2216                 return -1;
2217         }
2218
2219         drmModeFreeResources(resources);
2220
2221         return 0;
2222 }
2223
2224 static void
2225 update_outputs(struct drm_compositor *ec, struct udev_device *drm_device)
2226 {
2227         drmModeConnector *connector;
2228         drmModeRes *resources;
2229         struct drm_output *output, *next;
2230         int x = 0, y = 0;
2231         uint32_t connected = 0, disconnects = 0;
2232         int i;
2233
2234         resources = drmModeGetResources(ec->drm.fd);
2235         if (!resources) {
2236                 weston_log("drmModeGetResources failed\n");
2237                 return;
2238         }
2239
2240         /* collect new connects */
2241         for (i = 0; i < resources->count_connectors; i++) {
2242                 int connector_id = resources->connectors[i];
2243
2244                 connector = drmModeGetConnector(ec->drm.fd, connector_id);
2245                 if (connector == NULL)
2246                         continue;
2247
2248                 if (connector->connection != DRM_MODE_CONNECTED) {
2249                         drmModeFreeConnector(connector);
2250                         continue;
2251                 }
2252
2253                 connected |= (1 << connector_id);
2254
2255                 if (!(ec->connector_allocator & (1 << connector_id))) {
2256                         struct weston_output *last =
2257                                 container_of(ec->base.output_list.prev,
2258                                              struct weston_output, link);
2259
2260                         /* XXX: not yet needed, we die with 0 outputs */
2261                         if (!wl_list_empty(&ec->base.output_list))
2262                                 x = last->x + last->width;
2263                         else
2264                                 x = 0;
2265                         y = 0;
2266                         create_output_for_connector(ec, resources,
2267                                                     connector, x, y,
2268                                                     drm_device);
2269                         weston_log("connector %d connected\n", connector_id);
2270
2271                 }
2272                 drmModeFreeConnector(connector);
2273         }
2274         drmModeFreeResources(resources);
2275
2276         disconnects = ec->connector_allocator & ~connected;
2277         if (disconnects) {
2278                 wl_list_for_each_safe(output, next, &ec->base.output_list,
2279                                       base.link) {
2280                         if (disconnects & (1 << output->connector_id)) {
2281                                 disconnects &= ~(1 << output->connector_id);
2282                                 weston_log("connector %d disconnected\n",
2283                                        output->connector_id);
2284                                 drm_output_destroy(&output->base);
2285                         }
2286                 }
2287         }
2288
2289         /* FIXME: handle zero outputs, without terminating */   
2290         if (ec->connector_allocator == 0)
2291                 wl_display_terminate(ec->base.wl_display);
2292 }
2293
2294 static int
2295 udev_event_is_hotplug(struct drm_compositor *ec, struct udev_device *device)
2296 {
2297         const char *sysnum;
2298         const char *val;
2299
2300         sysnum = udev_device_get_sysnum(device);
2301         if (!sysnum || atoi(sysnum) != ec->drm.id)
2302                 return 0;
2303
2304         val = udev_device_get_property_value(device, "HOTPLUG");
2305         if (!val)
2306                 return 0;
2307
2308         return strcmp(val, "1") == 0;
2309 }
2310
2311 static int
2312 udev_drm_event(int fd, uint32_t mask, void *data)
2313 {
2314         struct drm_compositor *ec = data;
2315         struct udev_device *event;
2316
2317         event = udev_monitor_receive_device(ec->udev_monitor);
2318
2319         if (udev_event_is_hotplug(ec, event))
2320                 update_outputs(ec, event);
2321
2322         udev_device_unref(event);
2323
2324         return 1;
2325 }
2326
2327 static void
2328 drm_restore(struct weston_compositor *ec)
2329 {
2330         weston_launcher_restore(ec->launcher);
2331 }
2332
2333 static void
2334 drm_destroy(struct weston_compositor *ec)
2335 {
2336         struct drm_compositor *d = (struct drm_compositor *) ec;
2337
2338         udev_input_destroy(&d->input);
2339
2340         wl_event_source_remove(d->udev_drm_source);
2341         wl_event_source_remove(d->drm_source);
2342
2343         destroy_sprites(d);
2344
2345         weston_compositor_shutdown(ec);
2346
2347         if (d->gbm)
2348                 gbm_device_destroy(d->gbm);
2349
2350         weston_launcher_destroy(d->base.launcher);
2351
2352         close(d->drm.fd);
2353
2354         free(d);
2355 }
2356
2357 static void
2358 drm_compositor_set_modes(struct drm_compositor *compositor)
2359 {
2360         struct drm_output *output;
2361         struct drm_mode *drm_mode;
2362         int ret;
2363
2364         wl_list_for_each(output, &compositor->base.output_list, base.link) {
2365                 if (!output->current) {
2366                         /* If something that would cause the output to
2367                          * switch mode happened while in another vt, we
2368                          * might not have a current drm_fb. In that case,
2369                          * schedule a repaint and let drm_output_repaint
2370                          * handle setting the mode. */
2371                         weston_output_schedule_repaint(&output->base);
2372                         continue;
2373                 }
2374
2375                 drm_mode = (struct drm_mode *) output->base.current_mode;
2376                 ret = drmModeSetCrtc(compositor->drm.fd, output->crtc_id,
2377                                      output->current->fb_id, 0, 0,
2378                                      &output->connector_id, 1,
2379                                      &drm_mode->mode_info);
2380                 if (ret < 0) {
2381                         weston_log(
2382                                 "failed to set mode %dx%d for output at %d,%d: %m\n",
2383                                 drm_mode->base.width, drm_mode->base.height, 
2384                                 output->base.x, output->base.y);
2385                 }
2386         }
2387 }
2388
2389 static void
2390 session_notify(struct wl_listener *listener, void *data)
2391 {
2392         struct weston_compositor *compositor = data;
2393         struct drm_compositor *ec = data;
2394         struct drm_sprite *sprite;
2395         struct drm_output *output;
2396
2397         if (ec->base.session_active) {
2398                 weston_log("activating session\n");
2399                 compositor->state = ec->prev_state;
2400                 drm_compositor_set_modes(ec);
2401                 weston_compositor_damage_all(compositor);
2402                 udev_input_enable(&ec->input, ec->udev);
2403         } else {
2404                 weston_log("deactivating session\n");
2405                 udev_input_disable(&ec->input);
2406
2407                 ec->prev_state = compositor->state;
2408                 weston_compositor_offscreen(compositor);
2409
2410                 /* If we have a repaint scheduled (either from a
2411                  * pending pageflip or the idle handler), make sure we
2412                  * cancel that so we don't try to pageflip when we're
2413                  * vt switched away.  The OFFSCREEN state will prevent
2414                  * further attemps at repainting.  When we switch
2415                  * back, we schedule a repaint, which will process
2416                  * pending frame callbacks. */
2417
2418                 wl_list_for_each(output, &ec->base.output_list, base.link) {
2419                         output->base.repaint_needed = 0;
2420                         drmModeSetCursor(ec->drm.fd, output->crtc_id, 0, 0, 0);
2421                 }
2422
2423                 output = container_of(ec->base.output_list.next,
2424                                       struct drm_output, base.link);
2425
2426                 wl_list_for_each(sprite, &ec->sprite_list, link)
2427                         drmModeSetPlane(ec->drm.fd,
2428                                         sprite->plane_id,
2429                                         output->crtc_id, 0, 0,
2430                                         0, 0, 0, 0, 0, 0, 0, 0);
2431         };
2432 }
2433
2434 static void
2435 switch_vt_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *data)
2436 {
2437         struct weston_compositor *compositor = data;
2438
2439         weston_launcher_activate_vt(compositor->launcher, key - KEY_F1 + 1);
2440 }
2441
2442 /*
2443  * Find primary GPU
2444  * Some systems may have multiple DRM devices attached to a single seat. This
2445  * function loops over all devices and tries to find a PCI device with the
2446  * boot_vga sysfs attribute set to 1.
2447  * If no such device is found, the first DRM device reported by udev is used.
2448  */
2449 static struct udev_device*
2450 find_primary_gpu(struct drm_compositor *ec, const char *seat)
2451 {
2452         struct udev_enumerate *e;
2453         struct udev_list_entry *entry;
2454         const char *path, *device_seat, *id;
2455         struct udev_device *device, *drm_device, *pci;
2456
2457         e = udev_enumerate_new(ec->udev);
2458         udev_enumerate_add_match_subsystem(e, "drm");
2459         udev_enumerate_add_match_sysname(e, "card[0-9]*");
2460
2461         udev_enumerate_scan_devices(e);
2462         drm_device = NULL;
2463         udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
2464                 path = udev_list_entry_get_name(entry);
2465                 device = udev_device_new_from_syspath(ec->udev, path);
2466                 if (!device)
2467                         continue;
2468                 device_seat = udev_device_get_property_value(device, "ID_SEAT");
2469                 if (!device_seat)
2470                         device_seat = default_seat;
2471                 if (strcmp(device_seat, seat)) {
2472                         udev_device_unref(device);
2473                         continue;
2474                 }
2475
2476                 pci = udev_device_get_parent_with_subsystem_devtype(device,
2477                                                                 "pci", NULL);
2478                 if (pci) {
2479                         id = udev_device_get_sysattr_value(pci, "boot_vga");
2480                         if (id && !strcmp(id, "1")) {
2481                                 if (drm_device)
2482                                         udev_device_unref(drm_device);
2483                                 drm_device = device;
2484                                 break;
2485                         }
2486                 }
2487
2488                 if (!drm_device)
2489                         drm_device = device;
2490                 else
2491                         udev_device_unref(device);
2492         }
2493
2494         udev_enumerate_unref(e);
2495         return drm_device;
2496 }
2497
2498 static void
2499 planes_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *data)
2500 {
2501         struct drm_compositor *c = data;
2502
2503         switch (key) {
2504         case KEY_C:
2505                 c->cursors_are_broken ^= 1;
2506                 break;
2507         case KEY_V:
2508                 c->sprites_are_broken ^= 1;
2509                 break;
2510         case KEY_O:
2511                 c->sprites_hidden ^= 1;
2512                 break;
2513         default:
2514                 break;
2515         }
2516 }
2517
2518 #ifdef BUILD_VAAPI_RECORDER
2519 static void
2520 recorder_frame_notify(struct wl_listener *listener, void *data)
2521 {
2522         struct drm_output *output;
2523         struct drm_compositor *c;
2524         int fd, ret;
2525
2526         output = container_of(listener, struct drm_output,
2527                               recorder_frame_listener);
2528         c = (struct drm_compositor *) output->base.compositor;
2529
2530         if (!output->recorder)
2531                 return;
2532
2533         ret = drmPrimeHandleToFD(c->drm.fd, output->current->handle,
2534                                  DRM_CLOEXEC, &fd);
2535         if (ret) {
2536                 weston_log("[libva recorder] "
2537                            "failed to create prime fd for front buffer\n");
2538                 return;
2539         }
2540
2541         vaapi_recorder_frame(output->recorder, fd, output->current->stride / 4);
2542 }
2543
2544 static void *
2545 create_recorder(struct drm_compositor *c, int width, int height,
2546                 const char *filename)
2547 {
2548         int fd;
2549         drm_magic_t magic;
2550
2551         fd = open(c->drm.filename, O_RDWR | O_CLOEXEC);
2552         if (fd < 0)
2553                 return NULL;
2554
2555         drmGetMagic(fd, &magic);
2556         drmAuthMagic(c->drm.fd, magic);
2557
2558         return vaapi_recorder_create(fd, width, height, filename);
2559 }
2560
2561 static void
2562 recorder_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
2563                  void *data)
2564 {
2565         struct drm_compositor *c = data;
2566         struct drm_output *output;
2567         int width, height;
2568
2569         output = container_of(c->base.output_list.next,
2570                               struct drm_output, base.link);
2571
2572         if (!output->recorder) {
2573                 width = output->base.current_mode->width;
2574                 height = output->base.current_mode->height;
2575
2576                 output->recorder =
2577                         create_recorder(c, width, height, "capture.h264");
2578                 if (!output->recorder) {
2579                         weston_log("failed to create vaapi recorder\n");
2580                         return;
2581                 }
2582
2583                 output->base.disable_planes++;
2584
2585                 output->recorder_frame_listener.notify = recorder_frame_notify;
2586                 wl_signal_add(&output->base.frame_signal,
2587                               &output->recorder_frame_listener);
2588
2589                 weston_output_schedule_repaint(&output->base);
2590
2591                 weston_log("[libva recorder] initialized\n");
2592         } else {
2593                 vaapi_recorder_destroy(output->recorder);
2594                 output->recorder = NULL;
2595
2596                 output->base.disable_planes--;
2597
2598                 wl_list_remove(&output->recorder_frame_listener.link);
2599                 weston_log("[libva recorder] done\n");
2600         }
2601 }
2602 #else
2603 static void
2604 recorder_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
2605                  void *data)
2606 {
2607         weston_log("Compiled without libva support\n");
2608 }
2609 #endif
2610
2611 static void
2612 switch_to_gl_renderer(struct drm_compositor *c)
2613 {
2614         struct drm_output *output;
2615
2616         if (!c->use_pixman)
2617                 return;
2618
2619         weston_log("Switching to GL renderer\n");
2620
2621         c->gbm = create_gbm_device(c->drm.fd);
2622         if (!c->gbm) {
2623                 weston_log("Failed to create gbm device. "
2624                            "Aborting renderer switch\n");
2625                 return;
2626         }
2627
2628         wl_list_for_each(output, &c->base.output_list, base.link)
2629                 pixman_renderer_output_destroy(&output->base);
2630
2631         c->base.renderer->destroy(&c->base);
2632
2633         if (drm_compositor_create_gl_renderer(c) < 0) {
2634                 gbm_device_destroy(c->gbm);
2635                 weston_log("Failed to create GL renderer. Quitting.\n");
2636                 /* FIXME: we need a function to shutdown cleanly */
2637                 assert(0);
2638         }
2639
2640         wl_list_for_each(output, &c->base.output_list, base.link)
2641                 drm_output_init_egl(output, c);
2642
2643         c->use_pixman = 0;
2644 }
2645
2646 static void
2647 renderer_switch_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
2648                         void *data)
2649 {
2650         struct drm_compositor *c = (struct drm_compositor *) seat->compositor;
2651
2652         switch_to_gl_renderer(c);
2653 }
2654
2655 static struct weston_compositor *
2656 drm_compositor_create(struct wl_display *display,
2657                       struct drm_parameters *param,
2658                       int *argc, char *argv[],
2659                       struct weston_config *config)
2660 {
2661         struct drm_compositor *ec;
2662         struct weston_config_section *section;
2663         struct udev_device *drm_device;
2664         struct wl_event_loop *loop;
2665         const char *path;
2666         char *s;
2667         uint32_t key;
2668
2669         weston_log("initializing drm backend\n");
2670
2671         ec = zalloc(sizeof *ec);
2672         if (ec == NULL)
2673                 return NULL;
2674
2675         /* KMS support for sprites is not complete yet, so disable the
2676          * functionality for now. */
2677         ec->sprites_are_broken = 1;
2678
2679         section = weston_config_get_section(config, "core", NULL, NULL);
2680         weston_config_section_get_string(section,
2681                                          "gbm-format", &s, "xrgb8888");
2682         if (strcmp(s, "xrgb8888") == 0)
2683                 ec->format = GBM_FORMAT_XRGB8888;
2684         else if (strcmp(s, "rgb565") == 0)
2685                 ec->format = GBM_FORMAT_RGB565;
2686         else if (strcmp(s, "xrgb2101010") == 0)
2687                 ec->format = GBM_FORMAT_XRGB2101010;
2688         else {
2689                 weston_log("fatal: unrecognized pixel format: %s\n", s);
2690                 free(s);
2691                 goto err_base;
2692         }
2693         free(s);
2694
2695         ec->use_pixman = param->use_pixman;
2696
2697         if (weston_compositor_init(&ec->base, display, argc, argv,
2698                                    config) < 0) {
2699                 weston_log("%s failed\n", __func__);
2700                 goto err_base;
2701         }
2702
2703         /* Check if we run drm-backend using weston-launch */
2704         ec->base.launcher = weston_launcher_connect(&ec->base, param->tty,
2705                                                     param->seat_id);
2706         if (ec->base.launcher == NULL) {
2707                 weston_log("fatal: drm backend should be run "
2708                            "using weston-launch binary or as root\n");
2709                 goto err_compositor;
2710         }
2711
2712         ec->udev = udev_new();
2713         if (ec->udev == NULL) {
2714                 weston_log("failed to initialize udev context\n");
2715                 goto err_launcher;
2716         }
2717
2718         ec->base.wl_display = display;
2719         ec->session_listener.notify = session_notify;
2720         wl_signal_add(&ec->base.session_signal, &ec->session_listener);
2721
2722         drm_device = find_primary_gpu(ec, param->seat_id);
2723         if (drm_device == NULL) {
2724                 weston_log("no drm device found\n");
2725                 goto err_udev;
2726         }
2727         path = udev_device_get_syspath(drm_device);
2728
2729         if (init_drm(ec, drm_device) < 0) {
2730                 weston_log("failed to initialize kms\n");
2731                 goto err_udev_dev;
2732         }
2733
2734         if (ec->use_pixman) {
2735                 if (init_pixman(ec) < 0) {
2736                         weston_log("failed to initialize pixman renderer\n");
2737                         goto err_udev_dev;
2738                 }
2739         } else {
2740                 if (init_egl(ec) < 0) {
2741                         weston_log("failed to initialize egl\n");
2742                         goto err_udev_dev;
2743                 }
2744         }
2745
2746         ec->base.destroy = drm_destroy;
2747         ec->base.restore = drm_restore;
2748
2749         ec->prev_state = WESTON_COMPOSITOR_ACTIVE;
2750
2751         for (key = KEY_F1; key < KEY_F9; key++)
2752                 weston_compositor_add_key_binding(&ec->base, key,
2753                                                   MODIFIER_CTRL | MODIFIER_ALT,
2754                                                   switch_vt_binding, ec);
2755
2756         wl_list_init(&ec->sprite_list);
2757         create_sprites(ec);
2758
2759         if (create_outputs(ec, param->connector, drm_device) < 0) {
2760                 weston_log("failed to create output for %s\n", path);
2761                 goto err_sprite;
2762         }
2763
2764         path = NULL;
2765
2766         if (udev_input_init(&ec->input,
2767                             &ec->base, ec->udev, param->seat_id) < 0) {
2768                 weston_log("failed to create input devices\n");
2769                 goto err_sprite;
2770         }
2771
2772         loop = wl_display_get_event_loop(ec->base.wl_display);
2773         ec->drm_source =
2774                 wl_event_loop_add_fd(loop, ec->drm.fd,
2775                                      WL_EVENT_READABLE, on_drm_input, ec);
2776
2777         ec->udev_monitor = udev_monitor_new_from_netlink(ec->udev, "udev");
2778         if (ec->udev_monitor == NULL) {
2779                 weston_log("failed to intialize udev monitor\n");
2780                 goto err_drm_source;
2781         }
2782         udev_monitor_filter_add_match_subsystem_devtype(ec->udev_monitor,
2783                                                         "drm", NULL);
2784         ec->udev_drm_source =
2785                 wl_event_loop_add_fd(loop,
2786                                      udev_monitor_get_fd(ec->udev_monitor),
2787                                      WL_EVENT_READABLE, udev_drm_event, ec);
2788
2789         if (udev_monitor_enable_receiving(ec->udev_monitor) < 0) {
2790                 weston_log("failed to enable udev-monitor receiving\n");
2791                 goto err_udev_monitor;
2792         }
2793
2794         udev_device_unref(drm_device);
2795
2796         weston_compositor_add_debug_binding(&ec->base, KEY_O,
2797                                             planes_binding, ec);
2798         weston_compositor_add_debug_binding(&ec->base, KEY_C,
2799                                             planes_binding, ec);
2800         weston_compositor_add_debug_binding(&ec->base, KEY_V,
2801                                             planes_binding, ec);
2802         weston_compositor_add_debug_binding(&ec->base, KEY_Q,
2803                                             recorder_binding, ec);
2804         weston_compositor_add_debug_binding(&ec->base, KEY_W,
2805                                             renderer_switch_binding, ec);
2806
2807         return &ec->base;
2808
2809 err_udev_monitor:
2810         wl_event_source_remove(ec->udev_drm_source);
2811         udev_monitor_unref(ec->udev_monitor);
2812 err_drm_source:
2813         wl_event_source_remove(ec->drm_source);
2814         udev_input_destroy(&ec->input);
2815 err_sprite:
2816         ec->base.renderer->destroy(&ec->base);
2817         gbm_device_destroy(ec->gbm);
2818         destroy_sprites(ec);
2819 err_udev_dev:
2820         udev_device_unref(drm_device);
2821 err_launcher:
2822         weston_launcher_destroy(ec->base.launcher);
2823 err_udev:
2824         udev_unref(ec->udev);
2825 err_compositor:
2826         weston_compositor_shutdown(&ec->base);
2827 err_base:
2828         free(ec);
2829         return NULL;
2830 }
2831
2832 WL_EXPORT struct weston_compositor *
2833 backend_init(struct wl_display *display, int *argc, char *argv[],
2834              struct weston_config *config)
2835 {
2836         struct drm_parameters param = { 0, };
2837
2838         const struct weston_option drm_options[] = {
2839                 { WESTON_OPTION_INTEGER, "connector", 0, &param.connector },
2840                 { WESTON_OPTION_STRING, "seat", 0, &param.seat_id },
2841                 { WESTON_OPTION_INTEGER, "tty", 0, &param.tty },
2842                 { WESTON_OPTION_BOOLEAN, "current-mode", 0, &option_current_mode },
2843                 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &param.use_pixman },
2844         };
2845
2846         param.seat_id = default_seat;
2847
2848         parse_options(drm_options, ARRAY_LENGTH(drm_options), argc, argv);
2849
2850         return drm_compositor_create(display, &param, argc, argv, config);
2851 }