compositor-drm: log input device hot-unplugs
[profile/ivi/weston.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 #define _GNU_SOURCE
25
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <linux/input.h>
32 #include <assert.h>
33
34 #include <xf86drm.h>
35 #include <xf86drmMode.h>
36 #include <drm_fourcc.h>
37
38 #include <gbm.h>
39 #include <libbacklight.h>
40 #include <libudev.h>
41
42 #include "compositor.h"
43 #include "evdev.h"
44 #include "launcher-util.h"
45
46 static int option_current_mode = 0;
47 static char *output_name;
48 static char *output_mode;
49 static struct wl_list configured_output_list;
50
51 enum output_config {
52         OUTPUT_CONFIG_INVALID = 0,
53         OUTPUT_CONFIG_OFF,
54         OUTPUT_CONFIG_PREFERRED,
55         OUTPUT_CONFIG_CURRENT,
56         OUTPUT_CONFIG_MODE,
57         OUTPUT_CONFIG_MODELINE
58 };
59
60 struct drm_configured_output {
61         char *name;
62         char *mode;
63         int32_t width, height;
64         drmModeModeInfo crtc_mode;
65         enum output_config config;
66         struct wl_list link;
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         } drm;
82         struct gbm_device *gbm;
83         uint32_t *crtcs;
84         int num_crtcs;
85         uint32_t crtc_allocator;
86         uint32_t connector_allocator;
87         struct tty *tty;
88
89         struct gbm_surface *dummy_surface;
90         EGLSurface dummy_egl_surface;
91
92         struct wl_list sprite_list;
93         int sprites_are_broken;
94
95         uint32_t prev_state;
96 };
97
98 struct drm_mode {
99         struct weston_mode base;
100         drmModeModeInfo mode_info;
101 };
102
103 struct drm_output;
104
105 struct drm_fb {
106         struct gbm_bo *bo;
107         struct drm_output *output;
108         uint32_t fb_id;
109         int is_client_buffer;
110         struct wl_buffer *buffer;
111         struct wl_listener buffer_destroy_listener;
112 };
113
114 struct drm_output {
115         struct weston_output   base;
116
117         char *name;
118         uint32_t crtc_id;
119         uint32_t connector_id;
120         drmModeCrtcPtr original_crtc;
121
122         int vblank_pending;
123         int page_flip_pending;
124
125         struct gbm_surface *surface;
126         struct gbm_bo *cursor_bo[2];
127         struct weston_plane cursor_plane;
128         struct weston_plane fb_plane;
129         struct weston_surface *cursor_surface;
130         int current_cursor;
131         EGLSurface egl_surface;
132         struct drm_fb *current, *next;
133         struct backlight *backlight;
134 };
135
136 /*
137  * An output has a primary display plane plus zero or more sprites for
138  * blending display contents.
139  */
140 struct drm_sprite {
141         struct wl_list link;
142
143         uint32_t fb_id;
144         uint32_t pending_fb_id;
145         struct weston_surface *surface;
146         struct weston_surface *pending_surface;
147         struct weston_plane plane;
148
149         struct drm_output *output;
150
151         struct drm_compositor *compositor;
152
153         struct wl_listener destroy_listener;
154         struct wl_listener pending_destroy_listener;
155
156         uint32_t possible_crtcs;
157         uint32_t plane_id;
158         uint32_t count_formats;
159
160         int32_t src_x, src_y;
161         uint32_t src_w, src_h;
162         uint32_t dest_x, dest_y;
163         uint32_t dest_w, dest_h;
164
165         uint32_t formats[];
166 };
167
168 struct drm_seat {
169         struct weston_seat base;
170         struct wl_list devices_list;
171         struct udev_monitor *udev_monitor;
172         struct wl_event_source *udev_monitor_source;
173         char *seat_id;
174 };
175
176 static void
177 drm_output_set_cursor(struct drm_output *output);
178 static void
179 drm_disable_unused_sprites(struct weston_output *output_base);
180
181 static int
182 drm_sprite_crtc_supported(struct weston_output *output_base, uint32_t supported)
183 {
184         struct weston_compositor *ec = output_base->compositor;
185         struct drm_compositor *c =(struct drm_compositor *) ec;
186         struct drm_output *output = (struct drm_output *) output_base;
187         int crtc;
188
189         for (crtc = 0; crtc < c->num_crtcs; crtc++) {
190                 if (c->crtcs[crtc] != output->crtc_id)
191                         continue;
192
193                 if (supported & (1 << crtc))
194                         return -1;
195         }
196
197         return 0;
198 }
199
200 static void
201 drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
202 {
203         struct drm_fb *fb = data;
204         struct gbm_device *gbm = gbm_bo_get_device(bo);
205
206         if (fb->fb_id)
207                 drmModeRmFB(gbm_device_get_fd(gbm), fb->fb_id);
208
209         if (fb->buffer) {
210                 weston_buffer_post_release(fb->buffer);
211                 wl_list_remove(&fb->buffer_destroy_listener.link);
212         }
213
214         free(data);
215 }
216
217 static struct drm_fb *
218 drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_output *output)
219 {
220         struct drm_fb *fb = gbm_bo_get_user_data(bo);
221         struct drm_compositor *compositor =
222                 (struct drm_compositor *) output->base.compositor;
223         uint32_t width, height, stride, handle;
224         int ret;
225
226         if (fb)
227                 return fb;
228
229         fb = malloc(sizeof *fb);
230
231         fb->bo = bo;
232         fb->output = output;
233         fb->is_client_buffer = 0;
234         fb->buffer = NULL;
235
236         width = gbm_bo_get_width(bo);
237         height = gbm_bo_get_height(bo);
238         stride = gbm_bo_get_stride(bo);
239         handle = gbm_bo_get_handle(bo).u32;
240
241         ret = drmModeAddFB(compositor->drm.fd, width, height, 24, 32,
242                            stride, handle, &fb->fb_id);
243         if (ret) {
244                 weston_log("failed to create kms fb: %m\n");
245                 free(fb);
246                 return NULL;
247         }
248
249         gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback);
250
251         return fb;
252 }
253
254 static void
255 fb_handle_buffer_destroy(struct wl_listener *listener, void *data)
256 {
257         struct drm_fb *fb = container_of(listener, struct drm_fb,
258                                          buffer_destroy_listener);
259
260         fb->buffer = NULL;
261
262         if (fb == fb->output->next ||
263             (fb == fb->output->current && !fb->output->next))
264                 weston_output_schedule_repaint(&fb->output->base);
265 }
266
267 static struct weston_plane *
268 drm_output_prepare_scanout_surface(struct weston_output *_output,
269                                    struct weston_surface *es)
270 {
271         struct drm_output *output = (struct drm_output *) _output;
272         struct drm_compositor *c =
273                 (struct drm_compositor *) output->base.compositor;
274         struct gbm_bo *bo;
275
276         if (es->geometry.x != output->base.x ||
277             es->geometry.y != output->base.y ||
278             es->geometry.width != output->base.current->width ||
279             es->geometry.height != output->base.current->height ||
280             es->transform.enabled ||
281             es->buffer == NULL)
282                 return NULL;
283
284         bo = gbm_bo_import(c->gbm, GBM_BO_IMPORT_WL_BUFFER,
285                            es->buffer, GBM_BO_USE_SCANOUT);
286
287         /* Need to verify output->region contained in surface opaque
288          * region.  Or maybe just that format doesn't have alpha.
289          * For now, scanout only if format is XRGB8888. */
290         if (gbm_bo_get_format(bo) != GBM_FORMAT_XRGB8888) {
291                 gbm_bo_destroy(bo);
292                 return NULL;
293         }
294
295         output->next = drm_fb_get_from_bo(bo, output);
296         if (!output->next) {
297                 gbm_bo_destroy(bo);
298                 return NULL;
299         }
300
301         output->next->is_client_buffer = 1;
302         output->next->buffer = es->buffer;
303         output->next->buffer->busy_count++;
304         output->next->buffer_destroy_listener.notify = fb_handle_buffer_destroy;
305
306         wl_signal_add(&output->next->buffer->resource.destroy_signal,
307                       &output->next->buffer_destroy_listener);
308
309         return &output->fb_plane;
310 }
311
312 static void
313 drm_output_render(struct drm_output *output, pixman_region32_t *damage)
314 {
315         struct drm_compositor *compositor =
316                 (struct drm_compositor *) output->base.compositor;
317         struct weston_surface *surface;
318         struct gbm_bo *bo;
319
320         if (!eglMakeCurrent(compositor->base.egl_display, output->egl_surface,
321                             output->egl_surface,
322                             compositor->base.egl_context)) {
323                 weston_log("failed to make current\n");
324                 return;
325         }
326
327         wl_list_for_each_reverse(surface, &compositor->base.surface_list, link)
328                 if (surface->plane == &compositor->base.primary_plane)
329                         weston_surface_draw(surface, &output->base, damage);
330
331         wl_signal_emit(&output->base.frame_signal, output);
332
333         eglSwapBuffers(compositor->base.egl_display, output->egl_surface);
334         bo = gbm_surface_lock_front_buffer(output->surface);
335         if (!bo) {
336                 weston_log("failed to lock front buffer: %m\n");
337                 return;
338         }
339
340         output->next = drm_fb_get_from_bo(bo, output);
341         if (!output->next) {
342                 weston_log("failed to get drm_fb for bo\n");
343                 gbm_surface_release_buffer(output->surface, bo);
344                 return;
345         }
346 }
347
348 static void
349 drm_output_repaint(struct weston_output *output_base,
350                    pixman_region32_t *damage)
351 {
352         struct drm_output *output = (struct drm_output *) output_base;
353         struct drm_compositor *compositor =
354                 (struct drm_compositor *) output->base.compositor;
355         struct drm_sprite *s;
356         struct drm_mode *mode;
357         int ret = 0;
358
359         if (!output->next)
360                 drm_output_render(output, damage);
361         if (!output->next)
362                 return;
363
364         mode = container_of(output->base.current, struct drm_mode, base);
365         if (!output->current) {
366                 ret = drmModeSetCrtc(compositor->drm.fd, output->crtc_id,
367                                      output->next->fb_id, 0, 0,
368                                      &output->connector_id, 1,
369                                      &mode->mode_info);
370                 if (ret) {
371                         weston_log("set mode failed: %m\n");
372                         return;
373                 }
374         }
375
376         if (drmModePageFlip(compositor->drm.fd, output->crtc_id,
377                             output->next->fb_id,
378                             DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
379                 weston_log("queueing pageflip failed: %m\n");
380                 return;
381         }
382
383         output->page_flip_pending = 1;
384
385         drm_output_set_cursor(output);
386
387         /*
388          * Now, update all the sprite surfaces
389          */
390         wl_list_for_each(s, &compositor->sprite_list, link) {
391                 uint32_t flags = 0;
392                 drmVBlank vbl = {
393                         .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
394                         .request.sequence = 1,
395                 };
396
397                 if (!drm_sprite_crtc_supported(output_base, s->possible_crtcs))
398                         continue;
399
400                 ret = drmModeSetPlane(compositor->drm.fd, s->plane_id,
401                                       output->crtc_id, s->pending_fb_id, flags,
402                                       s->dest_x, s->dest_y,
403                                       s->dest_w, s->dest_h,
404                                       s->src_x, s->src_y,
405                                       s->src_w, s->src_h);
406                 if (ret)
407                         weston_log("setplane failed: %d: %s\n",
408                                 ret, strerror(errno));
409
410                 /*
411                  * Queue a vblank signal so we know when the surface
412                  * becomes active on the display or has been replaced.
413                  */
414                 vbl.request.signal = (unsigned long)s;
415                 ret = drmWaitVBlank(compositor->drm.fd, &vbl);
416                 if (ret) {
417                         weston_log("vblank event request failed: %d: %s\n",
418                                 ret, strerror(errno));
419                 }
420
421                 s->output = output;
422                 output->vblank_pending = 1;
423         }
424
425         drm_disable_unused_sprites(&output->base);
426
427         return;
428 }
429
430 static void
431 vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec,
432                void *data)
433 {
434         struct drm_sprite *s = (struct drm_sprite *)data;
435         struct drm_compositor *c = s->compositor;
436         struct drm_output *output = s->output;
437         uint32_t msecs;
438
439         output->vblank_pending = 0;
440
441         if (s->surface) {
442                 weston_buffer_post_release(s->surface->buffer);
443                 wl_list_remove(&s->destroy_listener.link);
444                 s->surface = NULL;
445                 drmModeRmFB(c->drm.fd, s->fb_id);
446                 s->fb_id = 0;
447         }
448
449         if (s->pending_surface) {
450                 wl_list_remove(&s->pending_destroy_listener.link);
451                 wl_signal_add(&s->pending_surface->buffer->resource.destroy_signal,
452                               &s->destroy_listener);
453                 s->surface = s->pending_surface;
454                 s->pending_surface = NULL;
455                 s->fb_id = s->pending_fb_id;
456                 s->pending_fb_id = 0;
457         }
458
459         if (!output->page_flip_pending) {
460                 msecs = sec * 1000 + usec / 1000;
461                 weston_output_finish_frame(&output->base, msecs);
462         }
463 }
464
465 static void
466 page_flip_handler(int fd, unsigned int frame,
467                   unsigned int sec, unsigned int usec, void *data)
468 {
469         struct drm_output *output = (struct drm_output *) data;
470         uint32_t msecs;
471
472         output->page_flip_pending = 0;
473
474         if (output->current) {
475                 if (output->current->is_client_buffer)
476                         gbm_bo_destroy(output->current->bo);
477                 else
478                         gbm_surface_release_buffer(output->surface,
479                                                    output->current->bo);
480         }
481
482         output->current = output->next;
483         output->next = NULL;
484
485         if (!output->vblank_pending) {
486                 msecs = sec * 1000 + usec / 1000;
487                 weston_output_finish_frame(&output->base, msecs);
488         }
489 }
490
491 static int
492 drm_surface_format_supported(struct drm_sprite *s, uint32_t format)
493 {
494         uint32_t i;
495
496         for (i = 0; i < s->count_formats; i++)
497                 if (s->formats[i] == format)
498                         return 1;
499
500         return 0;
501 }
502
503 static int
504 drm_surface_transform_supported(struct weston_surface *es)
505 {
506         struct weston_matrix *matrix = &es->transform.matrix;
507         int i;
508
509         if (!es->transform.enabled)
510                 return 1;
511
512         for (i = 0; i < 16; i++) {
513                 switch (i) {
514                 case 10:
515                 case 15:
516                         if (matrix->d[i] != 1.0)
517                                 return 0;
518                         break;
519                 case 0:
520                 case 5:
521                 case 12:
522                 case 13:
523                         break;
524                 default:
525                         if (matrix->d[i] != 0.0)
526                                 return 0;
527                         break;
528                 }
529         }
530
531         return 1;
532 }
533
534 static void
535 drm_disable_unused_sprites(struct weston_output *output_base)
536 {
537         struct weston_compositor *ec = output_base->compositor;
538         struct drm_compositor *c =(struct drm_compositor *) ec;
539         struct drm_output *output = (struct drm_output *) output_base;
540         struct drm_sprite *s;
541         int ret;
542
543         wl_list_for_each(s, &c->sprite_list, link) {
544                 if (s->pending_fb_id)
545                         continue;
546
547                 ret = drmModeSetPlane(c->drm.fd, s->plane_id,
548                                       output->crtc_id, 0, 0,
549                                       0, 0, 0, 0, 0, 0, 0, 0);
550                 if (ret)
551                         weston_log("failed to disable plane: %d: %s\n",
552                                 ret, strerror(errno));
553                 drmModeRmFB(c->drm.fd, s->fb_id);
554
555                 if (s->surface) {
556                         s->surface = NULL;
557                         wl_list_remove(&s->destroy_listener.link);
558                 }
559
560                 assert(!s->pending_surface);
561                 s->fb_id = 0;
562                 s->pending_fb_id = 0;
563         }
564 }
565
566 /*
567  * This function must take care to damage any previously assigned surface
568  * if the sprite ends up binding to a different surface than in the
569  * previous frame.
570  */
571 static struct weston_plane *
572 drm_output_prepare_overlay_surface(struct weston_output *output_base,
573                                    struct weston_surface *es)
574 {
575         struct weston_compositor *ec = output_base->compositor;
576         struct drm_compositor *c =(struct drm_compositor *) ec;
577         struct drm_sprite *s;
578         int found = 0;
579         EGLint handle, stride;
580         struct gbm_bo *bo;
581         uint32_t fb_id = 0;
582         uint32_t handles[4], pitches[4], offsets[4];
583         int ret = 0;
584         pixman_region32_t dest_rect, src_rect;
585         pixman_box32_t *box;
586         uint32_t format;
587         wl_fixed_t sx1, sy1, sx2, sy2;
588
589         if (c->sprites_are_broken)
590                 return NULL;
591
592         if (es->output_mask != (1u << output_base->id))
593                 return NULL;
594
595         if (es->buffer == NULL)
596                 return NULL;
597
598         if (!drm_surface_transform_supported(es))
599                 return NULL;
600
601         wl_list_for_each(s, &c->sprite_list, link) {
602                 if (!drm_sprite_crtc_supported(output_base, s->possible_crtcs))
603                         continue;
604
605                 if (!s->pending_fb_id) {
606                         found = 1;
607                         break;
608                 }
609         }
610
611         /* No sprites available */
612         if (!found)
613                 return NULL;
614
615         bo = gbm_bo_import(c->gbm, GBM_BO_IMPORT_WL_BUFFER,
616                            es->buffer, GBM_BO_USE_SCANOUT);
617         if (!bo)
618                 return NULL;
619
620         format = gbm_bo_get_format(bo);
621         handle = gbm_bo_get_handle(bo).s32;
622         stride = gbm_bo_get_stride(bo);
623
624         gbm_bo_destroy(bo);
625
626         if (!drm_surface_format_supported(s, format))
627                 return NULL;
628
629         if (!handle)
630                 return NULL;
631
632         handles[0] = handle;
633         pitches[0] = stride;
634         offsets[0] = 0;
635
636         ret = drmModeAddFB2(c->drm.fd, es->geometry.width, es->geometry.height,
637                             format, handles, pitches, offsets,
638                             &fb_id, 0);
639         if (ret) {
640                 weston_log("addfb2 failed: %d\n", ret);
641                 c->sprites_are_broken = 1;
642                 return NULL;
643         }
644
645         s->pending_fb_id = fb_id;
646         s->pending_surface = es;
647         es->buffer->busy_count++;
648
649         box = pixman_region32_extents(&es->transform.boundingbox);
650         s->plane.x = box->x1;
651         s->plane.y = box->y1;
652
653         /*
654          * Calculate the source & dest rects properly based on actual
655          * postion (note the caller has called weston_surface_update_transform()
656          * for us already).
657          */
658         pixman_region32_init(&dest_rect);
659         pixman_region32_intersect(&dest_rect, &es->transform.boundingbox,
660                                   &output_base->region);
661         pixman_region32_translate(&dest_rect, -output_base->x, -output_base->y);
662         box = pixman_region32_extents(&dest_rect);
663         s->dest_x = box->x1;
664         s->dest_y = box->y1;
665         s->dest_w = box->x2 - box->x1;
666         s->dest_h = box->y2 - box->y1;
667         pixman_region32_fini(&dest_rect);
668
669         pixman_region32_init(&src_rect);
670         pixman_region32_intersect(&src_rect, &es->transform.boundingbox,
671                                   &output_base->region);
672         box = pixman_region32_extents(&src_rect);
673
674         weston_surface_from_global_fixed(es,
675                                          wl_fixed_from_int(box->x1),
676                                          wl_fixed_from_int(box->y1),
677                                          &sx1, &sy1);
678         weston_surface_from_global_fixed(es,
679                                          wl_fixed_from_int(box->x2),
680                                          wl_fixed_from_int(box->y2),
681                                          &sx2, &sy2);
682
683         if (sx1 < 0)
684                 sx1 = 0;
685         if (sy1 < 0)
686                 sy1 = 0;
687         if (sx2 > wl_fixed_from_int(es->geometry.width))
688                 sx2 = wl_fixed_from_int(es->geometry.width);
689         if (sy2 > wl_fixed_from_int(es->geometry.height))
690                 sy2 = wl_fixed_from_int(es->geometry.height);
691
692         s->src_x = sx1 << 8;
693         s->src_y = sy1 << 8;
694         s->src_w = (sx2 - sx1) << 8;
695         s->src_h = (sy2 - sy1) << 8;
696         pixman_region32_fini(&src_rect);
697
698         wl_signal_add(&es->buffer->resource.destroy_signal,
699                       &s->pending_destroy_listener);
700
701         return &s->plane;
702 }
703
704 static struct weston_plane *
705 drm_output_prepare_cursor_surface(struct weston_output *output_base,
706                                   struct weston_surface *es)
707 {
708         struct drm_output *output = (struct drm_output *) output_base;
709
710         if (output->cursor_surface)
711                 return NULL;
712         if (es->output_mask != (1u << output_base->id))
713                 return NULL;
714         if (es->buffer == NULL || !wl_buffer_is_shm(es->buffer) ||
715             es->geometry.width > 64 || es->geometry.height > 64)
716                 return NULL;
717
718         output->cursor_surface = es;
719
720         return &output->cursor_plane;
721 }
722
723 static void
724 drm_output_set_cursor(struct drm_output *output)
725 {
726         struct weston_surface *es = output->cursor_surface;
727         struct drm_compositor *c =
728                 (struct drm_compositor *) output->base.compositor;
729         EGLint handle, stride;
730         struct gbm_bo *bo;
731         uint32_t buf[64 * 64];
732         unsigned char *s;
733         int i, x, y;
734
735         if (es == NULL) {
736                 drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
737                 return;
738         }
739
740         if (es->buffer && pixman_region32_not_empty(&output->cursor_plane.damage)) {
741                 pixman_region32_fini(&output->cursor_plane.damage);
742                 pixman_region32_init(&output->cursor_plane.damage);
743                 output->current_cursor ^= 1;
744                 bo = output->cursor_bo[output->current_cursor];
745                 memset(buf, 0, sizeof buf);
746                 stride = wl_shm_buffer_get_stride(es->buffer);
747                 s = wl_shm_buffer_get_data(es->buffer);
748                 for (i = 0; i < es->geometry.height; i++)
749                         memcpy(buf + i * 64, s + i * stride,
750                                es->geometry.width * 4);
751
752                 if (gbm_bo_write(bo, buf, sizeof buf) < 0)
753                         weston_log("failed update cursor: %n\n");
754
755                 handle = gbm_bo_get_handle(bo).s32;
756                 if (drmModeSetCursor(c->drm.fd,
757                                      output->crtc_id, handle, 64, 64))
758                         weston_log("failed to set cursor: %n\n");
759         }
760
761         x = es->geometry.x - output->base.x;
762         y = es->geometry.y - output->base.y;
763         if (output->cursor_plane.x != x || output->cursor_plane.y != y) {
764                 if (drmModeMoveCursor(c->drm.fd, output->crtc_id, x, y))
765                         weston_log("failed to move cursor: %m\n");
766                 output->cursor_plane.x = x;
767                 output->cursor_plane.y = y;
768         }
769 }
770
771 static void
772 drm_assign_planes(struct weston_output *output)
773 {
774         struct drm_compositor *c =
775                 (struct drm_compositor *) output->compositor;
776         struct drm_output *drm_output = (struct drm_output *) output;
777         struct weston_surface *es, *next;
778         pixman_region32_t overlap, surface_overlap;
779         struct weston_plane *primary, *next_plane;
780
781         /*
782          * Find a surface for each sprite in the output using some heuristics:
783          * 1) size
784          * 2) frequency of update
785          * 3) opacity (though some hw might support alpha blending)
786          * 4) clipping (this can be fixed with color keys)
787          *
788          * The idea is to save on blitting since this should save power.
789          * If we can get a large video surface on the sprite for example,
790          * the main display surface may not need to update at all, and
791          * the client buffer can be used directly for the sprite surface
792          * as we do for flipping full screen surfaces.
793          */
794         pixman_region32_init(&overlap);
795         drm_output->cursor_surface = NULL;
796         primary = &c->base.primary_plane;
797         wl_list_for_each_safe(es, next, &c->base.surface_list, link) {
798                 pixman_region32_init(&surface_overlap);
799                 pixman_region32_intersect(&surface_overlap, &overlap,
800                                           &es->transform.boundingbox);
801
802                 next_plane = NULL;
803                 if (pixman_region32_not_empty(&surface_overlap))
804                         next_plane = primary;
805                 if (next_plane == NULL)
806                         next_plane = drm_output_prepare_cursor_surface(output, es);
807                 if (next_plane == NULL)
808                         next_plane = drm_output_prepare_scanout_surface(output, es);
809                 if (next_plane == NULL)
810                         next_plane = drm_output_prepare_overlay_surface(output, es);
811                 if (next_plane == NULL)
812                         next_plane = primary;
813                 weston_surface_move_to_plane(es, next_plane);
814                 if (next_plane == primary)
815                         pixman_region32_union(&overlap, &overlap,
816                                               &es->transform.boundingbox);
817
818                 pixman_region32_fini(&surface_overlap);
819         }
820         pixman_region32_fini(&overlap);
821 }
822
823 static void
824 drm_output_destroy(struct weston_output *output_base)
825 {
826         struct drm_output *output = (struct drm_output *) output_base;
827         struct drm_compositor *c =
828                 (struct drm_compositor *) output->base.compositor;
829         drmModeCrtcPtr origcrtc = output->original_crtc;
830
831         if (output->backlight)
832                 backlight_destroy(output->backlight);
833
834         /* Turn off hardware cursor */
835         drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
836
837         /* Restore original CRTC state */
838         drmModeSetCrtc(c->drm.fd, origcrtc->crtc_id, origcrtc->buffer_id,
839                        origcrtc->x, origcrtc->y,
840                        &output->connector_id, 1, &origcrtc->mode);
841         drmModeFreeCrtc(origcrtc);
842
843         c->crtc_allocator &= ~(1 << output->crtc_id);
844         c->connector_allocator &= ~(1 << output->connector_id);
845
846         eglDestroySurface(c->base.egl_display, output->egl_surface);
847         gbm_surface_destroy(output->surface);
848
849         weston_plane_release(&output->fb_plane);
850         weston_plane_release(&output->cursor_plane);
851
852         weston_output_destroy(&output->base);
853         wl_list_remove(&output->base.link);
854
855         free(output->name);
856         free(output);
857 }
858
859 static struct drm_mode *
860 choose_mode (struct drm_output *output, struct weston_mode *target_mode)
861 {
862         struct drm_mode *tmp_mode = NULL, *mode;
863
864         if (output->base.current->width == target_mode->width && 
865             output->base.current->height == target_mode->height &&
866             (output->base.current->refresh == target_mode->refresh ||
867              target_mode->refresh == 0))
868                 return (struct drm_mode *)output->base.current;
869
870         wl_list_for_each(mode, &output->base.mode_list, base.link) {
871                 if (mode->mode_info.hdisplay == target_mode->width &&
872                     mode->mode_info.vdisplay == target_mode->height) {
873                         if (mode->mode_info.vrefresh == target_mode->refresh || 
874                             target_mode->refresh == 0) {
875                                 return mode;
876                         } else if (!tmp_mode) 
877                                 tmp_mode = mode;
878                 }
879         }
880
881         return tmp_mode;
882 }
883
884 static int
885 drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mode)
886 {
887         struct drm_output *output;
888         struct drm_mode *drm_mode;
889         int ret;
890         struct drm_compositor *ec;
891         struct gbm_surface *surface;
892         EGLSurface egl_surface;
893
894         if (output_base == NULL) {
895                 weston_log("output is NULL.\n");
896                 return -1;
897         }
898
899         if (mode == NULL) {
900                 weston_log("mode is NULL.\n");
901                 return -1;
902         }
903
904         ec = (struct drm_compositor *)output_base->compositor;
905         output = (struct drm_output *)output_base;
906         drm_mode  = choose_mode (output, mode);
907
908         if (!drm_mode) {
909                 weston_log("%s, invalid resolution:%dx%d\n", __func__, mode->width, mode->height);
910                 return -1;
911         } else if (&drm_mode->base == output->base.current) {
912                 return 0;
913         } else if (drm_mode->base.width == output->base.current->width &&
914                    drm_mode->base.height == output->base.current->height) {
915                 /* only change refresh value */
916                 ret = drmModeSetCrtc(ec->drm.fd,
917                                      output->crtc_id,
918                                      output->current->fb_id, 0, 0,
919                                      &output->connector_id, 1, &drm_mode->mode_info);
920
921                 if (ret) {
922                         weston_log("failed to set mode (%dx%d) %u Hz\n",
923                                 drm_mode->base.width,
924                                 drm_mode->base.height,
925                                 drm_mode->base.refresh / 1000);
926                         ret = -1;
927                 } else {
928                         output->base.current->flags = 0;
929                         output->base.current = &drm_mode->base;
930                         drm_mode->base.flags = 
931                                 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
932                         ret = 0;
933                 }
934
935                 return ret;
936         }
937
938         drm_mode->base.flags =
939                 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
940
941         surface = gbm_surface_create(ec->gbm,
942                                  drm_mode->base.width,
943                                  drm_mode->base.height,
944                                  GBM_FORMAT_XRGB8888,
945                                  GBM_BO_USE_SCANOUT |
946                                  GBM_BO_USE_RENDERING);
947         if (!surface) {
948                 weston_log("failed to create gbm surface\n");
949                 return -1;
950         }
951
952         egl_surface =
953                 eglCreateWindowSurface(ec->base.egl_display,
954                                        ec->base.egl_config,
955                                        surface, NULL);
956
957         if (egl_surface == EGL_NO_SURFACE) {
958                 weston_log("failed to create egl surface\n");
959                 goto err;
960         }
961
962         ret = drmModeSetCrtc(ec->drm.fd,
963                              output->crtc_id,
964                              output->current->fb_id, 0, 0,
965                              &output->connector_id, 1, &drm_mode->mode_info);
966         if (ret) {
967                 weston_log("failed to set mode\n");
968                 goto err;
969         }
970
971         /* reset rendering stuff. */
972         if (output->current) {
973                 if (output->current->is_client_buffer)
974                         gbm_bo_destroy(output->current->bo);
975                 else
976                         gbm_surface_release_buffer(output->surface,
977                                                    output->current->bo);
978         }
979         output->current = NULL;
980
981         if (output->next) {
982                 if (output->next->is_client_buffer)
983                         gbm_bo_destroy(output->next->bo);
984                 else
985                         gbm_surface_release_buffer(output->surface,
986                                                    output->next->bo);
987         }
988         output->next = NULL;
989
990         eglDestroySurface(ec->base.egl_display, output->egl_surface);
991         gbm_surface_destroy(output->surface);
992         output->egl_surface = egl_surface;
993         output->surface = surface;
994
995         /*update output*/
996         output->base.current = &drm_mode->base;
997         output->base.dirty = 1;
998         weston_output_move(&output->base, output->base.x, output->base.y);
999         return 0;
1000
1001 err:
1002         eglDestroySurface(ec->base.egl_display, egl_surface);
1003         gbm_surface_destroy(surface);
1004         return -1;
1005 }
1006
1007 static int
1008 on_drm_input(int fd, uint32_t mask, void *data)
1009 {
1010         drmEventContext evctx;
1011
1012         memset(&evctx, 0, sizeof evctx);
1013         evctx.version = DRM_EVENT_CONTEXT_VERSION;
1014         evctx.page_flip_handler = page_flip_handler;
1015         evctx.vblank_handler = vblank_handler;
1016         drmHandleEvent(fd, &evctx);
1017
1018         return 1;
1019 }
1020
1021 static int
1022 init_egl(struct drm_compositor *ec, struct udev_device *device)
1023 {
1024         EGLint major, minor, n;
1025         const char *filename, *sysnum;
1026         int fd;
1027         static const EGLint context_attribs[] = {
1028                 EGL_CONTEXT_CLIENT_VERSION, 2,
1029                 EGL_NONE
1030         };
1031
1032         static const EGLint config_attribs[] = {
1033                 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1034                 EGL_RED_SIZE, 1,
1035                 EGL_GREEN_SIZE, 1,
1036                 EGL_BLUE_SIZE, 1,
1037                 EGL_ALPHA_SIZE, 0,
1038                 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1039                 EGL_NONE
1040         };
1041
1042         sysnum = udev_device_get_sysnum(device);
1043         if (sysnum)
1044                 ec->drm.id = atoi(sysnum);
1045         if (!sysnum || ec->drm.id < 0) {
1046                 weston_log("cannot get device sysnum\n");
1047                 return -1;
1048         }
1049
1050         filename = udev_device_get_devnode(device);
1051         fd = open(filename, O_RDWR | O_CLOEXEC);
1052         if (fd < 0) {
1053                 /* Probably permissions error */
1054                 weston_log("couldn't open %s, skipping\n",
1055                         udev_device_get_devnode(device));
1056                 return -1;
1057         }
1058
1059         weston_log("using %s\n", filename);
1060
1061         ec->drm.fd = fd;
1062         ec->gbm = gbm_create_device(ec->drm.fd);
1063         ec->base.egl_display = eglGetDisplay(ec->gbm);
1064         if (ec->base.egl_display == NULL) {
1065                 weston_log("failed to create display\n");
1066                 return -1;
1067         }
1068
1069         if (!eglInitialize(ec->base.egl_display, &major, &minor)) {
1070                 weston_log("failed to initialize display\n");
1071                 return -1;
1072         }
1073
1074         if (!eglBindAPI(EGL_OPENGL_ES_API)) {
1075                 weston_log("failed to bind api EGL_OPENGL_ES_API\n");
1076                 return -1;
1077         }
1078
1079         if (!eglChooseConfig(ec->base.egl_display, config_attribs,
1080                              &ec->base.egl_config, 1, &n) || n != 1) {
1081                 weston_log("failed to choose config: %d\n", n);
1082                 return -1;
1083         }
1084
1085         ec->base.egl_context =
1086                 eglCreateContext(ec->base.egl_display, ec->base.egl_config,
1087                                  EGL_NO_CONTEXT, context_attribs);
1088         if (ec->base.egl_context == NULL) {
1089                 weston_log("failed to create context\n");
1090                 return -1;
1091         }
1092
1093         ec->dummy_surface = gbm_surface_create(ec->gbm, 10, 10,
1094                                                GBM_FORMAT_XRGB8888,
1095                                                GBM_BO_USE_RENDERING);
1096         if (!ec->dummy_surface) {
1097                 weston_log("failed to create dummy gbm surface\n");
1098                 return -1;
1099         }
1100
1101         ec->dummy_egl_surface =
1102                 eglCreateWindowSurface(ec->base.egl_display,
1103                                        ec->base.egl_config,
1104                                        ec->dummy_surface,
1105                                        NULL);
1106         if (ec->dummy_egl_surface == EGL_NO_SURFACE) {
1107                 weston_log("failed to create egl surface\n");
1108                 return -1;
1109         }
1110
1111         if (!eglMakeCurrent(ec->base.egl_display, ec->dummy_egl_surface,
1112                             ec->dummy_egl_surface, ec->base.egl_context)) {
1113                 weston_log("failed to make context current\n");
1114                 return -1;
1115         }
1116
1117         return 0;
1118 }
1119
1120 static int
1121 drm_output_add_mode(struct drm_output *output, drmModeModeInfo *info)
1122 {
1123         struct drm_mode *mode;
1124         uint64_t refresh;
1125
1126         mode = malloc(sizeof *mode);
1127         if (mode == NULL)
1128                 return -1;
1129
1130         mode->base.flags = 0;
1131         mode->base.width = info->hdisplay;
1132         mode->base.height = info->vdisplay;
1133
1134         /* Calculate higher precision (mHz) refresh rate */
1135         refresh = (info->clock * 1000000LL / info->htotal +
1136                    info->vtotal / 2) / info->vtotal;
1137
1138         if (info->flags & DRM_MODE_FLAG_INTERLACE)
1139                 refresh *= 2;
1140         if (info->flags & DRM_MODE_FLAG_DBLSCAN)
1141                 refresh /= 2;
1142         if (info->vscan > 1)
1143             refresh /= info->vscan;
1144
1145         mode->base.refresh = refresh;
1146         mode->mode_info = *info;
1147
1148         if (info->type & DRM_MODE_TYPE_PREFERRED)
1149                 mode->base.flags |= WL_OUTPUT_MODE_PREFERRED;
1150
1151         wl_list_insert(output->base.mode_list.prev, &mode->base.link);
1152
1153         return 0;
1154 }
1155
1156 static int
1157 drm_subpixel_to_wayland(int drm_value)
1158 {
1159         switch (drm_value) {
1160         default:
1161         case DRM_MODE_SUBPIXEL_UNKNOWN:
1162                 return WL_OUTPUT_SUBPIXEL_UNKNOWN;
1163         case DRM_MODE_SUBPIXEL_NONE:
1164                 return WL_OUTPUT_SUBPIXEL_NONE;
1165         case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
1166                 return WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB;
1167         case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
1168                 return WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR;
1169         case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
1170                 return WL_OUTPUT_SUBPIXEL_VERTICAL_RGB;
1171         case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
1172                 return WL_OUTPUT_SUBPIXEL_VERTICAL_BGR;
1173         }
1174 }
1175
1176 static void
1177 sprite_handle_buffer_destroy(struct wl_listener *listener, void *data)
1178 {
1179         struct drm_sprite *sprite =
1180                 container_of(listener, struct drm_sprite,
1181                              destroy_listener);
1182         struct drm_compositor *compositor = sprite->compositor;
1183
1184         sprite->surface = NULL;
1185         drmModeRmFB(compositor->drm.fd, sprite->fb_id);
1186         sprite->fb_id = 0;
1187 }
1188
1189 static void
1190 sprite_handle_pending_buffer_destroy(struct wl_listener *listener, void *data)
1191 {
1192         struct drm_sprite *sprite =
1193                 container_of(listener, struct drm_sprite,
1194                              pending_destroy_listener);
1195         struct drm_compositor *compositor = sprite->compositor;
1196
1197         sprite->pending_surface = NULL;
1198         drmModeRmFB(compositor->drm.fd, sprite->pending_fb_id);
1199         sprite->pending_fb_id = 0;
1200 }
1201
1202 /* returns a value between 0-255 range, where higher is brighter */
1203 static uint32_t
1204 drm_get_backlight(struct drm_output *output)
1205 {
1206         long brightness, max_brightness, norm;
1207
1208         brightness = backlight_get_brightness(output->backlight);
1209         max_brightness = backlight_get_max_brightness(output->backlight);
1210
1211         /* convert it on a scale of 0 to 255 */
1212         norm = (brightness * 255)/(max_brightness);
1213
1214         return (uint32_t) norm;
1215 }
1216
1217 /* values accepted are between 0-255 range */
1218 static void
1219 drm_set_backlight(struct weston_output *output_base, uint32_t value)
1220 {
1221         struct drm_output *output = (struct drm_output *) output_base;
1222         long max_brightness, new_brightness;
1223
1224         if (!output->backlight)
1225                 return;
1226
1227         if (value > 255)
1228                 return;
1229
1230         max_brightness = backlight_get_max_brightness(output->backlight);
1231
1232         /* get denormalized value */
1233         new_brightness = (value * max_brightness) / 255;
1234
1235         backlight_set_brightness(output->backlight, new_brightness);
1236 }
1237
1238 static drmModePropertyPtr
1239 drm_get_prop(int fd, drmModeConnectorPtr connector, const char *name)
1240 {
1241         drmModePropertyPtr props;
1242         int i;
1243
1244         for (i = 0; i < connector->count_props; i++) {
1245                 props = drmModeGetProperty(fd, connector->props[i]);
1246                 if (!props)
1247                         continue;
1248
1249                 if (!strcmp(props->name, name))
1250                         return props;
1251
1252                 drmModeFreeProperty(props);
1253         }
1254
1255         return NULL;
1256 }
1257
1258 static void
1259 drm_set_dpms(struct weston_output *output_base, enum dpms_enum level)
1260 {
1261         struct drm_output *output = (struct drm_output *) output_base;
1262         struct weston_compositor *ec = output_base->compositor;
1263         struct drm_compositor *c = (struct drm_compositor *) ec;
1264         drmModeConnectorPtr connector;
1265         drmModePropertyPtr prop;
1266
1267         connector = drmModeGetConnector(c->drm.fd, output->connector_id);
1268         if (!connector)
1269                 return;
1270
1271         prop = drm_get_prop(c->drm.fd, connector, "DPMS");
1272         if (!prop) {
1273                 drmModeFreeConnector(connector);
1274                 return;
1275         }
1276
1277         drmModeConnectorSetProperty(c->drm.fd, connector->connector_id,
1278                                     prop->prop_id, level);
1279         drmModeFreeProperty(prop);
1280         drmModeFreeConnector(connector);
1281 }
1282
1283 static const char *connector_type_names[] = {
1284         "None",
1285         "VGA",
1286         "DVI",
1287         "DVI",
1288         "DVI",
1289         "Composite",
1290         "TV",
1291         "LVDS",
1292         "CTV",
1293         "DIN",
1294         "DP",
1295         "HDMI",
1296         "HDMI",
1297         "TV",
1298         "eDP",
1299 };
1300
1301 static int
1302 find_crtc_for_connector(struct drm_compositor *ec,
1303                         drmModeRes *resources, drmModeConnector *connector)
1304 {
1305         drmModeEncoder *encoder;
1306         uint32_t possible_crtcs;
1307         int i, j;
1308
1309         for (j = 0; j < connector->count_encoders; j++) {
1310                 encoder = drmModeGetEncoder(ec->drm.fd, connector->encoders[j]);
1311                 if (encoder == NULL) {
1312                         weston_log("Failed to get encoder.\n");
1313                         return -1;
1314                 }
1315                 possible_crtcs = encoder->possible_crtcs;
1316                 drmModeFreeEncoder(encoder);
1317
1318                 for (i = 0; i < resources->count_crtcs; i++) {
1319                         if (possible_crtcs & (1 << i) &&
1320                             !(ec->crtc_allocator & (1 << resources->crtcs[i])))
1321                                 return i;
1322                 }
1323         }
1324
1325         return -1;
1326 }
1327
1328 static int
1329 create_output_for_connector(struct drm_compositor *ec,
1330                             drmModeRes *resources,
1331                             drmModeConnector *connector,
1332                             int x, int y, struct udev_device *drm_device)
1333 {
1334         struct drm_output *output;
1335         struct drm_mode *drm_mode, *next;
1336         struct weston_mode *m, *preferred, *current, *configured;
1337         struct drm_configured_output *o = NULL, *temp;
1338         drmModeEncoder *encoder;
1339         drmModeModeInfo crtc_mode;
1340         drmModeCrtc *crtc;
1341         int i, ret;
1342         char name[32];
1343         const char *type_name;
1344
1345         i = find_crtc_for_connector(ec, resources, connector);
1346         if (i < 0) {
1347                 weston_log("No usable crtc/encoder pair for connector.\n");
1348                 return -1;
1349         }
1350
1351         output = malloc(sizeof *output);
1352         if (output == NULL)
1353                 return -1;
1354
1355         memset(output, 0, sizeof *output);
1356         output->base.subpixel = drm_subpixel_to_wayland(connector->subpixel);
1357         output->base.make = "unknown";
1358         output->base.model = "unknown";
1359         wl_list_init(&output->base.mode_list);
1360
1361         if (connector->connector_type < ARRAY_LENGTH(connector_type_names))
1362                 type_name = connector_type_names[connector->connector_type];
1363         else
1364                 type_name = "UNKNOWN";
1365         snprintf(name, 32, "%s%d", type_name, connector->connector_type_id);
1366         output->name = strdup(name);
1367
1368         output->crtc_id = resources->crtcs[i];
1369         ec->crtc_allocator |= (1 << output->crtc_id);
1370         output->connector_id = connector->connector_id;
1371         ec->connector_allocator |= (1 << output->connector_id);
1372
1373         output->original_crtc = drmModeGetCrtc(ec->drm.fd, output->crtc_id);
1374
1375         /* Get the current mode on the crtc that's currently driving
1376          * this connector. */
1377         encoder = drmModeGetEncoder(ec->drm.fd, connector->encoder_id);
1378         memset(&crtc_mode, 0, sizeof crtc_mode);
1379         if (encoder != NULL) {
1380                 crtc = drmModeGetCrtc(ec->drm.fd, encoder->crtc_id);
1381                 drmModeFreeEncoder(encoder);
1382                 if (crtc == NULL)
1383                         goto err_free;
1384                 if (crtc->mode_valid)
1385                         crtc_mode = crtc->mode;
1386                 drmModeFreeCrtc(crtc);
1387         }
1388
1389         for (i = 0; i < connector->count_modes; i++) {
1390                 ret = drm_output_add_mode(output, &connector->modes[i]);
1391                 if (ret)
1392                         goto err_free;
1393         }
1394
1395         preferred = NULL;
1396         current = NULL;
1397         configured = NULL;
1398
1399         wl_list_for_each(temp, &configured_output_list, link) {
1400                 if (strcmp(temp->name, output->name) == 0) {
1401                         weston_log("%s mode \"%s\" in config\n",
1402                                                         temp->name, temp->mode);
1403                         o = temp;
1404                         break;
1405                 }
1406         }
1407
1408         if (o && strcmp("off", o->mode) == 0) {
1409                 weston_log("Disabling output %s\n", o->name);
1410
1411                 drmModeSetCrtc(ec->drm.fd, output->crtc_id,
1412                                                         0, 0, 0, 0, 0, NULL);
1413                 goto err_free;
1414         }
1415
1416         wl_list_for_each(drm_mode, &output->base.mode_list, base.link) {
1417                 if (o && o->width == drm_mode->base.width &&
1418                         o->height == drm_mode->base.height &&
1419                         o->config == OUTPUT_CONFIG_MODE)
1420                         configured = &drm_mode->base;
1421                 if (!memcmp(&crtc_mode, &drm_mode->mode_info, sizeof crtc_mode))
1422                         current = &drm_mode->base;
1423                 if (drm_mode->base.flags & WL_OUTPUT_MODE_PREFERRED)
1424                         preferred = &drm_mode->base;
1425         }
1426
1427         if (o && o->config == OUTPUT_CONFIG_MODELINE) {
1428                 ret = drm_output_add_mode(output, &o->crtc_mode);
1429                 if (ret)
1430                         goto err_free;
1431                 configured = container_of(output->base.mode_list.prev,
1432                                        struct weston_mode, link);
1433                 current = configured;
1434         }
1435
1436         if (current == NULL && crtc_mode.clock != 0) {
1437                 ret = drm_output_add_mode(output, &crtc_mode);
1438                 if (ret)
1439                         goto err_free;
1440                 current = container_of(output->base.mode_list.prev,
1441                                        struct weston_mode, link);
1442         }
1443
1444         if (o && o->config == OUTPUT_CONFIG_CURRENT)
1445                 configured = current;
1446
1447         if (option_current_mode && current)
1448                 output->base.current = current;
1449         else if (configured)
1450                 output->base.current = configured;
1451         else if (preferred)
1452                 output->base.current = preferred;
1453         else if (current)
1454                 output->base.current = current;
1455
1456         if (output->base.current == NULL) {
1457                 weston_log("no available modes for %s\n", output->name);
1458                 goto err_free;
1459         }
1460
1461         output->base.current->flags |= WL_OUTPUT_MODE_CURRENT;
1462
1463         output->surface = gbm_surface_create(ec->gbm,
1464                                              output->base.current->width,
1465                                              output->base.current->height,
1466                                              GBM_FORMAT_XRGB8888,
1467                                              GBM_BO_USE_SCANOUT |
1468                                              GBM_BO_USE_RENDERING);
1469         if (!output->surface) {
1470                 weston_log("failed to create gbm surface\n");
1471                 goto err_free;
1472         }
1473
1474         output->egl_surface =
1475                 eglCreateWindowSurface(ec->base.egl_display,
1476                                        ec->base.egl_config,
1477                                        output->surface,
1478                                        NULL);
1479         if (output->egl_surface == EGL_NO_SURFACE) {
1480                 weston_log("failed to create egl surface\n");
1481                 goto err_surface;
1482         }
1483
1484         output->cursor_bo[0] =
1485                 gbm_bo_create(ec->gbm, 64, 64, GBM_FORMAT_ARGB8888,
1486                               GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
1487         output->cursor_bo[1] =
1488                 gbm_bo_create(ec->gbm, 64, 64, GBM_FORMAT_ARGB8888,
1489                               GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
1490
1491         output->backlight = backlight_init(drm_device,
1492                                            connector->connector_type);
1493         if (output->backlight) {
1494                 output->base.set_backlight = drm_set_backlight;
1495                 output->base.backlight_current = drm_get_backlight(output);
1496         }
1497
1498         weston_output_init(&output->base, &ec->base, x, y,
1499                            connector->mmWidth, connector->mmHeight,
1500                            WL_OUTPUT_FLIPPED);
1501
1502         wl_list_insert(ec->base.output_list.prev, &output->base.link);
1503
1504         output->base.origin = output->base.current;
1505         output->base.repaint = drm_output_repaint;
1506         output->base.destroy = drm_output_destroy;
1507         output->base.assign_planes = drm_assign_planes;
1508         output->base.set_dpms = drm_set_dpms;
1509         output->base.switch_mode = drm_output_switch_mode;
1510
1511         weston_plane_init(&output->cursor_plane, 0, 0);
1512         weston_plane_init(&output->fb_plane, 0, 0);
1513
1514         weston_log("Output %s, (connector %d, crtc %d)\n",
1515                    output->name, output->connector_id, output->crtc_id);
1516         wl_list_for_each(m, &output->base.mode_list, link)
1517                 weston_log_continue("  mode %dx%d@%.1f%s%s%s\n",
1518                                     m->width, m->height, m->refresh / 1000.0,
1519                                     m->flags & WL_OUTPUT_MODE_PREFERRED ?
1520                                     ", preferred" : "",
1521                                     m->flags & WL_OUTPUT_MODE_CURRENT ?
1522                                     ", current" : "",
1523                                     connector->count_modes == 0 ?
1524                                     ", built-in" : "");
1525
1526         return 0;
1527
1528 err_surface:
1529         gbm_surface_destroy(output->surface);
1530 err_free:
1531         wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
1532                                                         base.link) {
1533                 wl_list_remove(&drm_mode->base.link);
1534                 free(drm_mode);
1535         }
1536
1537         drmModeFreeCrtc(output->original_crtc);
1538         ec->crtc_allocator &= ~(1 << output->crtc_id);
1539         ec->connector_allocator &= ~(1 << output->connector_id);
1540         free(output->name);
1541         free(output);
1542
1543         return -1;
1544 }
1545
1546 static void
1547 create_sprites(struct drm_compositor *ec)
1548 {
1549         struct drm_sprite *sprite;
1550         drmModePlaneRes *plane_res;
1551         drmModePlane *plane;
1552         uint32_t i;
1553
1554         plane_res = drmModeGetPlaneResources(ec->drm.fd);
1555         if (!plane_res) {
1556                 weston_log("failed to get plane resources: %s\n",
1557                         strerror(errno));
1558                 return;
1559         }
1560
1561         for (i = 0; i < plane_res->count_planes; i++) {
1562                 plane = drmModeGetPlane(ec->drm.fd, plane_res->planes[i]);
1563                 if (!plane)
1564                         continue;
1565
1566                 sprite = malloc(sizeof(*sprite) + ((sizeof(uint32_t)) *
1567                                                    plane->count_formats));
1568                 if (!sprite) {
1569                         weston_log("%s: out of memory\n",
1570                                 __func__);
1571                         free(plane);
1572                         continue;
1573                 }
1574
1575                 memset(sprite, 0, sizeof *sprite);
1576
1577                 sprite->possible_crtcs = plane->possible_crtcs;
1578                 sprite->plane_id = plane->plane_id;
1579                 sprite->surface = NULL;
1580                 sprite->pending_surface = NULL;
1581                 sprite->fb_id = 0;
1582                 sprite->pending_fb_id = 0;
1583                 sprite->destroy_listener.notify = sprite_handle_buffer_destroy;
1584                 sprite->pending_destroy_listener.notify =
1585                         sprite_handle_pending_buffer_destroy;
1586                 sprite->compositor = ec;
1587                 sprite->count_formats = plane->count_formats;
1588                 memcpy(sprite->formats, plane->formats,
1589                        plane->count_formats * sizeof(plane->formats[0]));
1590                 drmModeFreePlane(plane);
1591                 weston_plane_init(&sprite->plane, 0, 0);
1592
1593                 wl_list_insert(&ec->sprite_list, &sprite->link);
1594         }
1595
1596         free(plane_res->planes);
1597         free(plane_res);
1598 }
1599
1600 static void
1601 destroy_sprites(struct drm_compositor *compositor)
1602 {
1603         struct drm_sprite *sprite, *next;
1604         struct drm_output *output;
1605
1606         output = container_of(compositor->base.output_list.next,
1607                               struct drm_output, base.link);
1608
1609         wl_list_for_each_safe(sprite, next, &compositor->sprite_list, link) {
1610                 drmModeSetPlane(compositor->drm.fd,
1611                                 sprite->plane_id,
1612                                 output->crtc_id, 0, 0,
1613                                 0, 0, 0, 0, 0, 0, 0, 0);
1614                 drmModeRmFB(compositor->drm.fd, sprite->fb_id);
1615                 weston_plane_release(&sprite->plane);
1616                 free(sprite);
1617         }
1618 }
1619
1620 static int
1621 create_outputs(struct drm_compositor *ec, uint32_t option_connector,
1622                struct udev_device *drm_device)
1623 {
1624         drmModeConnector *connector;
1625         drmModeRes *resources;
1626         int i;
1627         int x = 0, y = 0;
1628
1629         resources = drmModeGetResources(ec->drm.fd);
1630         if (!resources) {
1631                 weston_log("drmModeGetResources failed\n");
1632                 return -1;
1633         }
1634
1635         ec->crtcs = calloc(resources->count_crtcs, sizeof(uint32_t));
1636         if (!ec->crtcs) {
1637                 drmModeFreeResources(resources);
1638                 return -1;
1639         }
1640
1641         ec->num_crtcs = resources->count_crtcs;
1642         memcpy(ec->crtcs, resources->crtcs, sizeof(uint32_t) * ec->num_crtcs);
1643
1644         for (i = 0; i < resources->count_connectors; i++) {
1645                 connector = drmModeGetConnector(ec->drm.fd,
1646                                                 resources->connectors[i]);
1647                 if (connector == NULL)
1648                         continue;
1649
1650                 if (connector->connection == DRM_MODE_CONNECTED &&
1651                     (option_connector == 0 ||
1652                      connector->connector_id == option_connector)) {
1653                         if (create_output_for_connector(ec, resources,
1654                                                         connector, x, y,
1655                                                         drm_device) < 0) {
1656                                 drmModeFreeConnector(connector);
1657                                 continue;
1658                         }
1659
1660                         x += container_of(ec->base.output_list.prev,
1661                                           struct weston_output,
1662                                           link)->current->width;
1663                 }
1664
1665                 drmModeFreeConnector(connector);
1666         }
1667
1668         if (wl_list_empty(&ec->base.output_list)) {
1669                 weston_log("No currently active connector found.\n");
1670                 drmModeFreeResources(resources);
1671                 return -1;
1672         }
1673
1674         drmModeFreeResources(resources);
1675
1676         return 0;
1677 }
1678
1679 static void
1680 update_outputs(struct drm_compositor *ec, struct udev_device *drm_device)
1681 {
1682         drmModeConnector *connector;
1683         drmModeRes *resources;
1684         struct drm_output *output, *next;
1685         int x = 0, y = 0;
1686         int x_offset = 0, y_offset = 0;
1687         uint32_t connected = 0, disconnects = 0;
1688         int i;
1689
1690         resources = drmModeGetResources(ec->drm.fd);
1691         if (!resources) {
1692                 weston_log("drmModeGetResources failed\n");
1693                 return;
1694         }
1695
1696         /* collect new connects */
1697         for (i = 0; i < resources->count_connectors; i++) {
1698                 int connector_id = resources->connectors[i];
1699
1700                 connector = drmModeGetConnector(ec->drm.fd, connector_id);
1701                 if (connector == NULL)
1702                         continue;
1703
1704                 if (connector->connection != DRM_MODE_CONNECTED) {
1705                         drmModeFreeConnector(connector);
1706                         continue;
1707                 }
1708
1709                 connected |= (1 << connector_id);
1710
1711                 if (!(ec->connector_allocator & (1 << connector_id))) {
1712                         struct weston_output *last =
1713                                 container_of(ec->base.output_list.prev,
1714                                              struct weston_output, link);
1715
1716                         /* XXX: not yet needed, we die with 0 outputs */
1717                         if (!wl_list_empty(&ec->base.output_list))
1718                                 x = last->x + last->current->width;
1719                         else
1720                                 x = 0;
1721                         y = 0;
1722                         create_output_for_connector(ec, resources,
1723                                                     connector, x, y,
1724                                                     drm_device);
1725                         weston_log("connector %d connected\n", connector_id);
1726
1727                 }
1728                 drmModeFreeConnector(connector);
1729         }
1730         drmModeFreeResources(resources);
1731
1732         disconnects = ec->connector_allocator & ~connected;
1733         if (disconnects) {
1734                 wl_list_for_each_safe(output, next, &ec->base.output_list,
1735                                       base.link) {
1736                         if (x_offset != 0 || y_offset != 0) {
1737                                 weston_output_move(&output->base,
1738                                                  output->base.x - x_offset,
1739                                                  output->base.y - y_offset);
1740                         }
1741
1742                         if (disconnects & (1 << output->connector_id)) {
1743                                 disconnects &= ~(1 << output->connector_id);
1744                                 weston_log("connector %d disconnected\n",
1745                                        output->connector_id);
1746                                 x_offset += output->base.current->width;
1747                                 drm_output_destroy(&output->base);
1748                         }
1749                 }
1750         }
1751
1752         /* FIXME: handle zero outputs, without terminating */   
1753         if (ec->connector_allocator == 0)
1754                 wl_display_terminate(ec->base.wl_display);
1755 }
1756
1757 static int
1758 udev_event_is_hotplug(struct drm_compositor *ec, struct udev_device *device)
1759 {
1760         const char *sysnum;
1761         const char *val;
1762
1763         sysnum = udev_device_get_sysnum(device);
1764         if (!sysnum || atoi(sysnum) != ec->drm.id)
1765                 return 0;
1766
1767         val = udev_device_get_property_value(device, "HOTPLUG");
1768         if (!val)
1769                 return 0;
1770
1771         return strcmp(val, "1") == 0;
1772 }
1773
1774 static int
1775 udev_drm_event(int fd, uint32_t mask, void *data)
1776 {
1777         struct drm_compositor *ec = data;
1778         struct udev_device *event;
1779
1780         event = udev_monitor_receive_device(ec->udev_monitor);
1781
1782         if (udev_event_is_hotplug(ec, event))
1783                 update_outputs(ec, event);
1784
1785         udev_device_unref(event);
1786
1787         return 1;
1788 }
1789
1790 static void
1791 drm_restore(struct weston_compositor *ec)
1792 {
1793         struct drm_compositor *d = (struct drm_compositor *) ec;
1794
1795         if (weston_launcher_drm_set_master(&d->base, d->drm.fd, 0) < 0)
1796                 weston_log("failed to drop master: %m\n");
1797         tty_reset(d->tty);
1798 }
1799
1800 static const char default_seat[] = "seat0";
1801
1802 static void
1803 device_added(struct udev_device *udev_device, struct drm_seat *master)
1804 {
1805         struct weston_compositor *c;
1806         struct evdev_input_device *device;
1807         const char *devnode;
1808         const char *device_seat;
1809         int fd;
1810
1811         device_seat = udev_device_get_property_value(udev_device, "ID_SEAT");
1812         if (!device_seat)
1813                 device_seat = default_seat;
1814
1815         if (strcmp(device_seat, master->seat_id))
1816                 return;
1817
1818         c = master->base.compositor;
1819         devnode = udev_device_get_devnode(udev_device);
1820
1821         /* Use non-blocking mode so that we can loop on read on
1822          * evdev_input_device_data() until all events on the fd are
1823          * read.  mtdev_get() also expects this. */
1824         fd = weston_launcher_open(c, devnode, O_RDWR | O_NONBLOCK);
1825         if (fd < 0) {
1826                 weston_log("opening input device '%s' failed.\n", devnode);
1827                 return;
1828         }
1829
1830         device = evdev_input_device_create(&master->base, devnode, fd);
1831         if (!device) {
1832                 close(fd);
1833                 weston_log("not using input device '%s'.\n", devnode);
1834                 return;
1835         }
1836
1837         wl_list_insert(master->devices_list.prev, &device->link);
1838 }
1839
1840 static void
1841 evdev_add_devices(struct udev *udev, struct weston_seat *seat_base)
1842 {
1843         struct drm_seat *seat = (struct drm_seat *) seat_base;
1844         struct udev_enumerate *e;
1845         struct udev_list_entry *entry;
1846         struct udev_device *device;
1847         const char *path, *sysname;
1848
1849         e = udev_enumerate_new(udev);
1850         udev_enumerate_add_match_subsystem(e, "input");
1851         udev_enumerate_scan_devices(e);
1852         udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
1853                 path = udev_list_entry_get_name(entry);
1854                 device = udev_device_new_from_syspath(udev, path);
1855
1856                 sysname = udev_device_get_sysname(device);
1857                 if (strncmp("event", sysname, 5) != 0) {
1858                         udev_device_unref(device);
1859                         continue;
1860                 }
1861
1862                 device_added(device, seat);
1863
1864                 udev_device_unref(device);
1865         }
1866         udev_enumerate_unref(e);
1867
1868         evdev_notify_keyboard_focus(&seat->base, &seat->devices_list);
1869
1870         if (wl_list_empty(&seat->devices_list)) {
1871                 weston_log(
1872                         "warning: no input devices on entering Weston. "
1873                         "Possible causes:\n"
1874                         "\t- no permissions to read /dev/input/event*\n"
1875                         "\t- seats misconfigured "
1876                         "(Weston backend option 'seat', "
1877                         "udev device property ID_SEAT)\n");
1878         }
1879 }
1880
1881 static int
1882 evdev_udev_handler(int fd, uint32_t mask, void *data)
1883 {
1884         struct drm_seat *seat = data;
1885         struct udev_device *udev_device;
1886         struct evdev_input_device *device, *next;
1887         const char *action;
1888         const char *devnode;
1889
1890         udev_device = udev_monitor_receive_device(seat->udev_monitor);
1891         if (!udev_device)
1892                 return 1;
1893
1894         action = udev_device_get_action(udev_device);
1895         if (!action)
1896                 goto out;
1897
1898         if (strncmp("event", udev_device_get_sysname(udev_device), 5) != 0)
1899                 goto out;
1900
1901         if (!strcmp(action, "add")) {
1902                 device_added(udev_device, seat);
1903         }
1904         else if (!strcmp(action, "remove")) {
1905                 devnode = udev_device_get_devnode(udev_device);
1906                 wl_list_for_each_safe(device, next, &seat->devices_list, link)
1907                         if (!strcmp(device->devnode, devnode)) {
1908                                 weston_log("input device %s, %s removed\n",
1909                                            device->devname, device->devnode);
1910                                 evdev_input_device_destroy(device);
1911                                 break;
1912                         }
1913         }
1914
1915 out:
1916         udev_device_unref(udev_device);
1917
1918         return 0;
1919 }
1920
1921 static int
1922 evdev_enable_udev_monitor(struct udev *udev, struct weston_seat *seat_base)
1923 {
1924         struct drm_seat *master = (struct drm_seat *) seat_base;
1925         struct wl_event_loop *loop;
1926         struct weston_compositor *c = master->base.compositor;
1927         int fd;
1928
1929         master->udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
1930         if (!master->udev_monitor) {
1931                 weston_log("udev: failed to create the udev monitor\n");
1932                 return 0;
1933         }
1934
1935         udev_monitor_filter_add_match_subsystem_devtype(master->udev_monitor,
1936                         "input", NULL);
1937
1938         if (udev_monitor_enable_receiving(master->udev_monitor)) {
1939                 weston_log("udev: failed to bind the udev monitor\n");
1940                 udev_monitor_unref(master->udev_monitor);
1941                 return 0;
1942         }
1943
1944         loop = wl_display_get_event_loop(c->wl_display);
1945         fd = udev_monitor_get_fd(master->udev_monitor);
1946         master->udev_monitor_source =
1947                 wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
1948                                      evdev_udev_handler, master);
1949         if (!master->udev_monitor_source) {
1950                 udev_monitor_unref(master->udev_monitor);
1951                 return 0;
1952         }
1953
1954         return 1;
1955 }
1956
1957 static void
1958 evdev_disable_udev_monitor(struct weston_seat *seat_base)
1959 {
1960         struct drm_seat *seat = (struct drm_seat *) seat_base;
1961
1962         if (!seat->udev_monitor)
1963                 return;
1964
1965         udev_monitor_unref(seat->udev_monitor);
1966         seat->udev_monitor = NULL;
1967         wl_event_source_remove(seat->udev_monitor_source);
1968         seat->udev_monitor_source = NULL;
1969 }
1970
1971 static void
1972 drm_led_update(struct weston_seat *seat_base, enum weston_led leds)
1973 {
1974         struct drm_seat *seat = (struct drm_seat *) seat_base;
1975
1976         evdev_led_update(&seat->devices_list, leds);
1977 }
1978
1979 static void
1980 evdev_input_create(struct weston_compositor *c, struct udev *udev,
1981                    const char *seat_id)
1982 {
1983         struct drm_seat *seat;
1984
1985         seat = malloc(sizeof *seat);
1986         if (seat == NULL)
1987                 return;
1988
1989         memset(seat, 0, sizeof *seat);
1990         weston_seat_init(&seat->base, c);
1991         seat->base.led_update = drm_led_update;
1992
1993         wl_list_init(&seat->devices_list);
1994         seat->seat_id = strdup(seat_id);
1995         if (!evdev_enable_udev_monitor(udev, &seat->base)) {
1996                 free(seat->seat_id);
1997                 free(seat);
1998                 return;
1999         }
2000
2001         evdev_add_devices(udev, &seat->base);
2002
2003         c->seat = &seat->base;
2004 }
2005
2006 static void
2007 evdev_remove_devices(struct weston_seat *seat_base)
2008 {
2009         struct drm_seat *seat = (struct drm_seat *) seat_base;
2010         struct evdev_input_device *device, *next;
2011
2012         wl_list_for_each_safe(device, next, &seat->devices_list, link)
2013                 evdev_input_device_destroy(device);
2014
2015         notify_keyboard_focus_out(&seat->base.seat);
2016 }
2017
2018 static void
2019 evdev_input_destroy(struct weston_seat *seat_base)
2020 {
2021         struct drm_seat *seat = (struct drm_seat *) seat_base;
2022
2023         evdev_remove_devices(seat_base);
2024         evdev_disable_udev_monitor(&seat->base);
2025
2026         weston_seat_release(seat_base);
2027         free(seat->seat_id);
2028         free(seat);
2029 }
2030
2031 static void
2032 drm_free_configured_output(struct drm_configured_output *output)
2033 {
2034         free(output->name);
2035         free(output->mode);
2036         free(output);
2037 }
2038
2039 static void
2040 drm_destroy(struct weston_compositor *ec)
2041 {
2042         struct drm_compositor *d = (struct drm_compositor *) ec;
2043         struct weston_seat *seat, *next;
2044         struct drm_configured_output *o, *n;
2045
2046         wl_list_for_each_safe(seat, next, &ec->seat_list, link)
2047                 evdev_input_destroy(seat);
2048         wl_list_for_each_safe(o, n, &configured_output_list, link)
2049                 drm_free_configured_output(o);
2050
2051         wl_event_source_remove(d->udev_drm_source);
2052         wl_event_source_remove(d->drm_source);
2053
2054         weston_compositor_shutdown(ec);
2055
2056         /* Work around crash in egl_dri2.c's dri2_make_current() */
2057         eglMakeCurrent(ec->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
2058                        EGL_NO_CONTEXT);
2059         eglTerminate(ec->egl_display);
2060         eglReleaseThread();
2061
2062         gbm_device_destroy(d->gbm);
2063         destroy_sprites(d);
2064         if (weston_launcher_drm_set_master(&d->base, d->drm.fd, 0) < 0)
2065                 weston_log("failed to drop master: %m\n");
2066         tty_destroy(d->tty);
2067
2068         free(d);
2069 }
2070
2071 static void
2072 drm_compositor_set_modes(struct drm_compositor *compositor)
2073 {
2074         struct drm_output *output;
2075         struct drm_mode *drm_mode;
2076         int ret;
2077
2078         wl_list_for_each(output, &compositor->base.output_list, base.link) {
2079                 drm_mode = (struct drm_mode *) output->base.current;
2080                 ret = drmModeSetCrtc(compositor->drm.fd, output->crtc_id,
2081                                      output->current->fb_id, 0, 0,
2082                                      &output->connector_id, 1,
2083                                      &drm_mode->mode_info);
2084                 if (ret < 0) {
2085                         weston_log(
2086                                 "failed to set mode %dx%d for output at %d,%d: %m\n",
2087                                 drm_mode->base.width, drm_mode->base.height, 
2088                                 output->base.x, output->base.y);
2089                 }
2090         }
2091 }
2092
2093 static void
2094 vt_func(struct weston_compositor *compositor, int event)
2095 {
2096         struct drm_compositor *ec = (struct drm_compositor *) compositor;
2097         struct weston_seat *seat;
2098         struct drm_sprite *sprite;
2099         struct drm_output *output;
2100
2101         switch (event) {
2102         case TTY_ENTER_VT:
2103                 compositor->focus = 1;
2104                 if (weston_launcher_drm_set_master(&ec->base, ec->drm.fd, 1)) {
2105                         weston_log("failed to set master: %m\n");
2106                         wl_display_terminate(compositor->wl_display);
2107                 }
2108                 compositor->state = ec->prev_state;
2109                 drm_compositor_set_modes(ec);
2110                 weston_compositor_damage_all(compositor);
2111                 wl_list_for_each(seat, &compositor->seat_list, link) {
2112                         evdev_add_devices(ec->udev, seat);
2113                         evdev_enable_udev_monitor(ec->udev, seat);
2114                 }
2115                 break;
2116         case TTY_LEAVE_VT:
2117                 wl_list_for_each(seat, &compositor->seat_list, link) {
2118                         evdev_disable_udev_monitor(seat);
2119                         evdev_remove_devices(seat);
2120                 }
2121
2122                 compositor->focus = 0;
2123                 ec->prev_state = compositor->state;
2124                 compositor->state = WESTON_COMPOSITOR_SLEEPING;
2125
2126                 /* If we have a repaint scheduled (either from a
2127                  * pending pageflip or the idle handler), make sure we
2128                  * cancel that so we don't try to pageflip when we're
2129                  * vt switched away.  The SLEEPING state will prevent
2130                  * further attemps at repainting.  When we switch
2131                  * back, we schedule a repaint, which will process
2132                  * pending frame callbacks. */
2133
2134                 wl_list_for_each(output, &ec->base.output_list, base.link) {
2135                         output->base.repaint_needed = 0;
2136                         drmModeSetCursor(ec->drm.fd, output->crtc_id, 0, 0, 0);
2137                 }
2138
2139                 output = container_of(ec->base.output_list.next,
2140                                       struct drm_output, base.link);
2141
2142                 wl_list_for_each(sprite, &ec->sprite_list, link)
2143                         drmModeSetPlane(ec->drm.fd,
2144                                         sprite->plane_id,
2145                                         output->crtc_id, 0, 0,
2146                                         0, 0, 0, 0, 0, 0, 0, 0);
2147
2148                 if (weston_launcher_drm_set_master(&ec->base, ec->drm.fd, 0) < 0)
2149                         weston_log("failed to drop master: %m\n");
2150
2151                 break;
2152         };
2153 }
2154
2155 static void
2156 switch_vt_binding(struct wl_seat *seat, uint32_t time, uint32_t key, void *data)
2157 {
2158         struct drm_compositor *ec = data;
2159
2160         tty_activate_vt(ec->tty, key - KEY_F1 + 1);
2161 }
2162
2163 static struct weston_compositor *
2164 drm_compositor_create(struct wl_display *display,
2165                       int connector, const char *seat, int tty,
2166                       int argc, char *argv[], const char *config_file)
2167 {
2168         struct drm_compositor *ec;
2169         struct udev_enumerate *e;
2170         struct udev_list_entry *entry;
2171         struct udev_device *device, *drm_device;
2172         const char *path, *device_seat;
2173         struct wl_event_loop *loop;
2174         struct weston_seat *weston_seat, *next;
2175         uint32_t key;
2176
2177         weston_log("initializing drm backend\n");
2178
2179         ec = malloc(sizeof *ec);
2180         if (ec == NULL)
2181                 return NULL;
2182         memset(ec, 0, sizeof *ec);
2183
2184         if (weston_compositor_init(&ec->base, display, argc, argv,
2185                                    config_file) < 0) {
2186                 weston_log("weston_compositor_init failed\n");
2187                 goto err_base;
2188         }
2189
2190         ec->udev = udev_new();
2191         if (ec->udev == NULL) {
2192                 weston_log("failed to initialize udev context\n");
2193                 goto err_compositor;
2194         }
2195
2196         ec->base.wl_display = display;
2197         ec->tty = tty_create(&ec->base, vt_func, tty);
2198         if (!ec->tty) {
2199                 weston_log("failed to initialize tty\n");
2200                 goto err_udev;
2201         }
2202
2203         e = udev_enumerate_new(ec->udev);
2204         udev_enumerate_add_match_subsystem(e, "drm");
2205         udev_enumerate_add_match_sysname(e, "card[0-9]*");
2206
2207         udev_enumerate_scan_devices(e);
2208         drm_device = NULL;
2209         udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
2210                 path = udev_list_entry_get_name(entry);
2211                 device = udev_device_new_from_syspath(ec->udev, path);
2212                 device_seat =
2213                         udev_device_get_property_value(device, "ID_SEAT");
2214                 if (!device_seat)
2215                         device_seat = default_seat;
2216                 if (strcmp(device_seat, seat) == 0) {
2217                         drm_device = device;
2218                         break;
2219                 }
2220                 udev_device_unref(device);
2221         }
2222
2223         if (drm_device == NULL) {
2224                 weston_log("no drm device found\n");
2225                 goto err_udev_enum;
2226         }
2227
2228         if (init_egl(ec, drm_device) < 0) {
2229                 weston_log("failed to initialize egl\n");
2230                 goto err_udev_dev;
2231         }
2232
2233         ec->base.destroy = drm_destroy;
2234         ec->base.restore = drm_restore;
2235
2236         ec->base.focus = 1;
2237
2238         ec->prev_state = WESTON_COMPOSITOR_ACTIVE;
2239
2240         if (weston_compositor_init_gl(&ec->base) < 0)
2241                 goto err_egl;
2242
2243         for (key = KEY_F1; key < KEY_F9; key++)
2244                 weston_compositor_add_key_binding(&ec->base, key,
2245                                                   MODIFIER_CTRL | MODIFIER_ALT,
2246                                                   switch_vt_binding, ec);
2247
2248         wl_list_init(&ec->sprite_list);
2249         create_sprites(ec);
2250
2251         if (create_outputs(ec, connector, drm_device) < 0) {
2252                 weston_log("failed to create output for %s\n", path);
2253                 goto err_sprite;
2254         }
2255
2256         path = NULL;
2257
2258         evdev_input_create(&ec->base, ec->udev, seat);
2259
2260         loop = wl_display_get_event_loop(ec->base.wl_display);
2261         ec->drm_source =
2262                 wl_event_loop_add_fd(loop, ec->drm.fd,
2263                                      WL_EVENT_READABLE, on_drm_input, ec);
2264
2265         ec->udev_monitor = udev_monitor_new_from_netlink(ec->udev, "udev");
2266         if (ec->udev_monitor == NULL) {
2267                 weston_log("failed to intialize udev monitor\n");
2268                 goto err_drm_source;
2269         }
2270         udev_monitor_filter_add_match_subsystem_devtype(ec->udev_monitor,
2271                                                         "drm", NULL);
2272         ec->udev_drm_source =
2273                 wl_event_loop_add_fd(loop,
2274                                      udev_monitor_get_fd(ec->udev_monitor),
2275                                      WL_EVENT_READABLE, udev_drm_event, ec);
2276
2277         if (udev_monitor_enable_receiving(ec->udev_monitor) < 0) {
2278                 weston_log("failed to enable udev-monitor receiving\n");
2279                 goto err_udev_monitor;
2280         }
2281
2282         udev_device_unref(drm_device);
2283         udev_enumerate_unref(e);
2284
2285         return &ec->base;
2286
2287 err_udev_monitor:
2288         wl_event_source_remove(ec->udev_drm_source);
2289         udev_monitor_unref(ec->udev_monitor);
2290 err_drm_source:
2291         wl_event_source_remove(ec->drm_source);
2292         wl_list_for_each_safe(weston_seat, next, &ec->base.seat_list, link)
2293                 evdev_input_destroy(weston_seat);
2294 err_sprite:
2295         destroy_sprites(ec);
2296 err_egl:
2297         eglMakeCurrent(ec->base.egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
2298                        EGL_NO_CONTEXT);
2299         eglTerminate(ec->base.egl_display);
2300         eglReleaseThread();
2301         gbm_device_destroy(ec->gbm);
2302 err_udev_dev:
2303         udev_device_unref(drm_device);
2304 err_udev_enum:
2305         udev_enumerate_unref(e);
2306         tty_destroy(ec->tty);
2307 err_udev:
2308         udev_unref(ec->udev);
2309 err_compositor:
2310         weston_compositor_shutdown(&ec->base);
2311 err_base:
2312         free(ec);
2313         return NULL;
2314 }
2315
2316 static int
2317 set_sync_flags(drmModeModeInfo *mode, char *hsync, char *vsync)
2318 {
2319         mode->flags = 0;
2320
2321         if (strcmp(hsync, "+hsync") == 0)
2322                 mode->flags |= DRM_MODE_FLAG_PHSYNC;
2323         else if (strcmp(hsync, "-hsync") == 0)
2324                 mode->flags |= DRM_MODE_FLAG_NHSYNC;
2325         else
2326                 return -1;
2327
2328         if (strcmp(vsync, "+vsync") == 0)
2329                 mode->flags |= DRM_MODE_FLAG_PVSYNC;
2330         else if (strcmp(vsync, "-vsync") == 0)
2331                 mode->flags |= DRM_MODE_FLAG_NVSYNC;
2332         else
2333                 return -1;
2334
2335         return 0;
2336 }
2337
2338 static int
2339 check_for_modeline(struct drm_configured_output *output)
2340 {
2341         drmModeModeInfo mode;
2342         char hsync[16];
2343         char vsync[16];
2344         char mode_name[16];
2345         float fclock;
2346
2347         mode.type = DRM_MODE_TYPE_USERDEF;
2348         mode.hskew = 0;
2349         mode.vscan = 0;
2350         mode.vrefresh = 0;
2351
2352         if (sscanf(output_mode, "%f %hd %hd %hd %hd %hd %hd %hd %hd %s %s",
2353                                                 &fclock, &mode.hdisplay,
2354                                                 &mode.hsync_start,
2355                                                 &mode.hsync_end, &mode.htotal,
2356                                                 &mode.vdisplay,
2357                                                 &mode.vsync_start,
2358                                                 &mode.vsync_end, &mode.vtotal,
2359                                                 hsync, vsync) == 11) {
2360                 if (set_sync_flags(&mode, hsync, vsync))
2361                         return -1;
2362
2363                 sprintf(mode_name, "%dx%d", mode.hdisplay, mode.vdisplay);
2364                 strcpy(mode.name, mode_name);
2365
2366                 mode.clock = fclock * 1000;
2367         } else
2368                 return -1;
2369
2370         output->crtc_mode = mode;
2371
2372         return 0;
2373 }
2374
2375 static void
2376 output_section_done(void *data)
2377 {
2378         struct drm_configured_output *output;
2379
2380         output = malloc(sizeof *output);
2381
2382         if (!output || !output_name || !output_mode) {
2383                 free(output_name);
2384                 output_name = NULL;
2385                 free(output_mode);
2386                 output_mode = NULL;
2387                 return;
2388         }
2389
2390         output->config = OUTPUT_CONFIG_INVALID;
2391         output->name = output_name;
2392         output->mode = output_mode;
2393
2394         if (strcmp(output_mode, "off") == 0)
2395                 output->config = OUTPUT_CONFIG_OFF;
2396         else if (strcmp(output_mode, "preferred") == 0)
2397                 output->config = OUTPUT_CONFIG_PREFERRED;
2398         else if (strcmp(output_mode, "current") == 0)
2399                 output->config = OUTPUT_CONFIG_CURRENT;
2400         else if (sscanf(output_mode, "%dx%d", &output->width, &output->height) == 2)
2401                 output->config = OUTPUT_CONFIG_MODE;
2402         else if (check_for_modeline(output) == 0)
2403                 output->config = OUTPUT_CONFIG_MODELINE;
2404
2405         if (output->config != OUTPUT_CONFIG_INVALID)
2406                 wl_list_insert(&configured_output_list, &output->link);
2407         else {
2408                 weston_log("Invalid mode \"%s\" for output %s\n",
2409                                                 output_mode, output_name);
2410                 drm_free_configured_output(output);
2411         }
2412 }
2413
2414 WL_EXPORT struct weston_compositor *
2415 backend_init(struct wl_display *display, int argc, char *argv[],
2416              const char *config_file)
2417 {
2418         int connector = 0, tty = 0;
2419         const char *seat = default_seat;
2420
2421         const struct weston_option drm_options[] = {
2422                 { WESTON_OPTION_INTEGER, "connector", 0, &connector },
2423                 { WESTON_OPTION_STRING, "seat", 0, &seat },
2424                 { WESTON_OPTION_INTEGER, "tty", 0, &tty },
2425                 { WESTON_OPTION_BOOLEAN, "current-mode", 0, &option_current_mode },
2426         };
2427
2428         parse_options(drm_options, ARRAY_LENGTH(drm_options), argc, argv);
2429
2430         wl_list_init(&configured_output_list);
2431
2432         const struct config_key drm_config_keys[] = {
2433                 { "name", CONFIG_KEY_STRING, &output_name },
2434                 { "mode", CONFIG_KEY_STRING, &output_mode },
2435         };
2436
2437         const struct config_section config_section[] = {
2438                 { "output", drm_config_keys,
2439                 ARRAY_LENGTH(drm_config_keys), output_section_done },
2440         };
2441
2442         parse_config_file(config_file, config_section,
2443                                 ARRAY_LENGTH(config_section), NULL);
2444
2445         return drm_compositor_create(display, connector, seat, tty, argc, argv,
2446                                      config_file);
2447 }