compositor-drm: Disable planes when zoomed or capturing
[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         output->cursor_surface = NULL;
736         if (es == NULL) {
737                 drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
738                 return;
739         }
740
741         if (es->buffer && pixman_region32_not_empty(&output->cursor_plane.damage)) {
742                 pixman_region32_fini(&output->cursor_plane.damage);
743                 pixman_region32_init(&output->cursor_plane.damage);
744                 output->current_cursor ^= 1;
745                 bo = output->cursor_bo[output->current_cursor];
746                 memset(buf, 0, sizeof buf);
747                 stride = wl_shm_buffer_get_stride(es->buffer);
748                 s = wl_shm_buffer_get_data(es->buffer);
749                 for (i = 0; i < es->geometry.height; i++)
750                         memcpy(buf + i * 64, s + i * stride,
751                                es->geometry.width * 4);
752
753                 if (gbm_bo_write(bo, buf, sizeof buf) < 0)
754                         weston_log("failed update cursor: %n\n");
755
756                 handle = gbm_bo_get_handle(bo).s32;
757                 if (drmModeSetCursor(c->drm.fd,
758                                      output->crtc_id, handle, 64, 64))
759                         weston_log("failed to set cursor: %n\n");
760         }
761
762         x = es->geometry.x - output->base.x;
763         y = es->geometry.y - output->base.y;
764         if (output->cursor_plane.x != x || output->cursor_plane.y != y) {
765                 if (drmModeMoveCursor(c->drm.fd, output->crtc_id, x, y))
766                         weston_log("failed to move cursor: %m\n");
767                 output->cursor_plane.x = x;
768                 output->cursor_plane.y = y;
769         }
770 }
771
772 static void
773 drm_assign_planes(struct weston_output *output)
774 {
775         struct drm_compositor *c =
776                 (struct drm_compositor *) output->compositor;
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         primary = &c->base.primary_plane;
796         wl_list_for_each_safe(es, next, &c->base.surface_list, link) {
797                 pixman_region32_init(&surface_overlap);
798                 pixman_region32_intersect(&surface_overlap, &overlap,
799                                           &es->transform.boundingbox);
800
801                 next_plane = NULL;
802                 if (pixman_region32_not_empty(&surface_overlap))
803                         next_plane = primary;
804                 if (next_plane == NULL)
805                         next_plane = drm_output_prepare_cursor_surface(output, es);
806                 if (next_plane == NULL)
807                         next_plane = drm_output_prepare_scanout_surface(output, es);
808                 if (next_plane == NULL)
809                         next_plane = drm_output_prepare_overlay_surface(output, es);
810                 if (next_plane == NULL)
811                         next_plane = primary;
812                 weston_surface_move_to_plane(es, next_plane);
813                 if (next_plane == primary)
814                         pixman_region32_union(&overlap, &overlap,
815                                               &es->transform.boundingbox);
816
817                 pixman_region32_fini(&surface_overlap);
818         }
819         pixman_region32_fini(&overlap);
820 }
821
822 static void
823 drm_output_destroy(struct weston_output *output_base)
824 {
825         struct drm_output *output = (struct drm_output *) output_base;
826         struct drm_compositor *c =
827                 (struct drm_compositor *) output->base.compositor;
828         drmModeCrtcPtr origcrtc = output->original_crtc;
829
830         if (output->backlight)
831                 backlight_destroy(output->backlight);
832
833         /* Turn off hardware cursor */
834         drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
835
836         /* Restore original CRTC state */
837         drmModeSetCrtc(c->drm.fd, origcrtc->crtc_id, origcrtc->buffer_id,
838                        origcrtc->x, origcrtc->y,
839                        &output->connector_id, 1, &origcrtc->mode);
840         drmModeFreeCrtc(origcrtc);
841
842         c->crtc_allocator &= ~(1 << output->crtc_id);
843         c->connector_allocator &= ~(1 << output->connector_id);
844
845         eglDestroySurface(c->base.egl_display, output->egl_surface);
846         gbm_surface_destroy(output->surface);
847
848         weston_plane_release(&output->fb_plane);
849         weston_plane_release(&output->cursor_plane);
850
851         weston_output_destroy(&output->base);
852         wl_list_remove(&output->base.link);
853
854         free(output->name);
855         free(output);
856 }
857
858 static struct drm_mode *
859 choose_mode (struct drm_output *output, struct weston_mode *target_mode)
860 {
861         struct drm_mode *tmp_mode = NULL, *mode;
862
863         if (output->base.current->width == target_mode->width && 
864             output->base.current->height == target_mode->height &&
865             (output->base.current->refresh == target_mode->refresh ||
866              target_mode->refresh == 0))
867                 return (struct drm_mode *)output->base.current;
868
869         wl_list_for_each(mode, &output->base.mode_list, base.link) {
870                 if (mode->mode_info.hdisplay == target_mode->width &&
871                     mode->mode_info.vdisplay == target_mode->height) {
872                         if (mode->mode_info.vrefresh == target_mode->refresh || 
873                             target_mode->refresh == 0) {
874                                 return mode;
875                         } else if (!tmp_mode) 
876                                 tmp_mode = mode;
877                 }
878         }
879
880         return tmp_mode;
881 }
882
883 static int
884 drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mode)
885 {
886         struct drm_output *output;
887         struct drm_mode *drm_mode;
888         int ret;
889         struct drm_compositor *ec;
890         struct gbm_surface *surface;
891         EGLSurface egl_surface;
892
893         if (output_base == NULL) {
894                 weston_log("output is NULL.\n");
895                 return -1;
896         }
897
898         if (mode == NULL) {
899                 weston_log("mode is NULL.\n");
900                 return -1;
901         }
902
903         ec = (struct drm_compositor *)output_base->compositor;
904         output = (struct drm_output *)output_base;
905         drm_mode  = choose_mode (output, mode);
906
907         if (!drm_mode) {
908                 weston_log("%s, invalid resolution:%dx%d\n", __func__, mode->width, mode->height);
909                 return -1;
910         } else if (&drm_mode->base == output->base.current) {
911                 return 0;
912         } else if (drm_mode->base.width == output->base.current->width &&
913                    drm_mode->base.height == output->base.current->height) {
914                 /* only change refresh value */
915                 ret = drmModeSetCrtc(ec->drm.fd,
916                                      output->crtc_id,
917                                      output->current->fb_id, 0, 0,
918                                      &output->connector_id, 1, &drm_mode->mode_info);
919
920                 if (ret) {
921                         weston_log("failed to set mode (%dx%d) %u Hz\n",
922                                 drm_mode->base.width,
923                                 drm_mode->base.height,
924                                 drm_mode->base.refresh / 1000);
925                         ret = -1;
926                 } else {
927                         output->base.current->flags = 0;
928                         output->base.current = &drm_mode->base;
929                         drm_mode->base.flags = 
930                                 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
931                         ret = 0;
932                 }
933
934                 return ret;
935         }
936
937         drm_mode->base.flags =
938                 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
939
940         surface = gbm_surface_create(ec->gbm,
941                                  drm_mode->base.width,
942                                  drm_mode->base.height,
943                                  GBM_FORMAT_XRGB8888,
944                                  GBM_BO_USE_SCANOUT |
945                                  GBM_BO_USE_RENDERING);
946         if (!surface) {
947                 weston_log("failed to create gbm surface\n");
948                 return -1;
949         }
950
951         egl_surface =
952                 eglCreateWindowSurface(ec->base.egl_display,
953                                        ec->base.egl_config,
954                                        surface, NULL);
955
956         if (egl_surface == EGL_NO_SURFACE) {
957                 weston_log("failed to create egl surface\n");
958                 goto err;
959         }
960
961         ret = drmModeSetCrtc(ec->drm.fd,
962                              output->crtc_id,
963                              output->current->fb_id, 0, 0,
964                              &output->connector_id, 1, &drm_mode->mode_info);
965         if (ret) {
966                 weston_log("failed to set mode\n");
967                 goto err;
968         }
969
970         /* reset rendering stuff. */
971         if (output->current) {
972                 if (output->current->is_client_buffer)
973                         gbm_bo_destroy(output->current->bo);
974                 else
975                         gbm_surface_release_buffer(output->surface,
976                                                    output->current->bo);
977         }
978         output->current = NULL;
979
980         if (output->next) {
981                 if (output->next->is_client_buffer)
982                         gbm_bo_destroy(output->next->bo);
983                 else
984                         gbm_surface_release_buffer(output->surface,
985                                                    output->next->bo);
986         }
987         output->next = NULL;
988
989         eglDestroySurface(ec->base.egl_display, output->egl_surface);
990         gbm_surface_destroy(output->surface);
991         output->egl_surface = egl_surface;
992         output->surface = surface;
993
994         /*update output*/
995         output->base.current = &drm_mode->base;
996         output->base.dirty = 1;
997         weston_output_move(&output->base, output->base.x, output->base.y);
998         return 0;
999
1000 err:
1001         eglDestroySurface(ec->base.egl_display, egl_surface);
1002         gbm_surface_destroy(surface);
1003         return -1;
1004 }
1005
1006 static int
1007 on_drm_input(int fd, uint32_t mask, void *data)
1008 {
1009         drmEventContext evctx;
1010
1011         memset(&evctx, 0, sizeof evctx);
1012         evctx.version = DRM_EVENT_CONTEXT_VERSION;
1013         evctx.page_flip_handler = page_flip_handler;
1014         evctx.vblank_handler = vblank_handler;
1015         drmHandleEvent(fd, &evctx);
1016
1017         return 1;
1018 }
1019
1020 static int
1021 init_egl(struct drm_compositor *ec, struct udev_device *device)
1022 {
1023         EGLint major, minor, n;
1024         const char *filename, *sysnum;
1025         int fd;
1026         static const EGLint context_attribs[] = {
1027                 EGL_CONTEXT_CLIENT_VERSION, 2,
1028                 EGL_NONE
1029         };
1030
1031         static const EGLint config_attribs[] = {
1032                 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1033                 EGL_RED_SIZE, 1,
1034                 EGL_GREEN_SIZE, 1,
1035                 EGL_BLUE_SIZE, 1,
1036                 EGL_ALPHA_SIZE, 0,
1037                 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1038                 EGL_NONE
1039         };
1040
1041         sysnum = udev_device_get_sysnum(device);
1042         if (sysnum)
1043                 ec->drm.id = atoi(sysnum);
1044         if (!sysnum || ec->drm.id < 0) {
1045                 weston_log("cannot get device sysnum\n");
1046                 return -1;
1047         }
1048
1049         filename = udev_device_get_devnode(device);
1050         fd = open(filename, O_RDWR | O_CLOEXEC);
1051         if (fd < 0) {
1052                 /* Probably permissions error */
1053                 weston_log("couldn't open %s, skipping\n",
1054                         udev_device_get_devnode(device));
1055                 return -1;
1056         }
1057
1058         weston_log("using %s\n", filename);
1059
1060         ec->drm.fd = fd;
1061         ec->gbm = gbm_create_device(ec->drm.fd);
1062         ec->base.egl_display = eglGetDisplay(ec->gbm);
1063         if (ec->base.egl_display == NULL) {
1064                 weston_log("failed to create display\n");
1065                 return -1;
1066         }
1067
1068         if (!eglInitialize(ec->base.egl_display, &major, &minor)) {
1069                 weston_log("failed to initialize display\n");
1070                 return -1;
1071         }
1072
1073         if (!eglBindAPI(EGL_OPENGL_ES_API)) {
1074                 weston_log("failed to bind api EGL_OPENGL_ES_API\n");
1075                 return -1;
1076         }
1077
1078         if (!eglChooseConfig(ec->base.egl_display, config_attribs,
1079                              &ec->base.egl_config, 1, &n) || n != 1) {
1080                 weston_log("failed to choose config: %d\n", n);
1081                 return -1;
1082         }
1083
1084         ec->base.egl_context =
1085                 eglCreateContext(ec->base.egl_display, ec->base.egl_config,
1086                                  EGL_NO_CONTEXT, context_attribs);
1087         if (ec->base.egl_context == NULL) {
1088                 weston_log("failed to create context\n");
1089                 return -1;
1090         }
1091
1092         ec->dummy_surface = gbm_surface_create(ec->gbm, 10, 10,
1093                                                GBM_FORMAT_XRGB8888,
1094                                                GBM_BO_USE_RENDERING);
1095         if (!ec->dummy_surface) {
1096                 weston_log("failed to create dummy gbm surface\n");
1097                 return -1;
1098         }
1099
1100         ec->dummy_egl_surface =
1101                 eglCreateWindowSurface(ec->base.egl_display,
1102                                        ec->base.egl_config,
1103                                        ec->dummy_surface,
1104                                        NULL);
1105         if (ec->dummy_egl_surface == EGL_NO_SURFACE) {
1106                 weston_log("failed to create egl surface\n");
1107                 return -1;
1108         }
1109
1110         if (!eglMakeCurrent(ec->base.egl_display, ec->dummy_egl_surface,
1111                             ec->dummy_egl_surface, ec->base.egl_context)) {
1112                 weston_log("failed to make context current\n");
1113                 return -1;
1114         }
1115
1116         return 0;
1117 }
1118
1119 static int
1120 drm_output_add_mode(struct drm_output *output, drmModeModeInfo *info)
1121 {
1122         struct drm_mode *mode;
1123         uint64_t refresh;
1124
1125         mode = malloc(sizeof *mode);
1126         if (mode == NULL)
1127                 return -1;
1128
1129         mode->base.flags = 0;
1130         mode->base.width = info->hdisplay;
1131         mode->base.height = info->vdisplay;
1132
1133         /* Calculate higher precision (mHz) refresh rate */
1134         refresh = (info->clock * 1000000LL / info->htotal +
1135                    info->vtotal / 2) / info->vtotal;
1136
1137         if (info->flags & DRM_MODE_FLAG_INTERLACE)
1138                 refresh *= 2;
1139         if (info->flags & DRM_MODE_FLAG_DBLSCAN)
1140                 refresh /= 2;
1141         if (info->vscan > 1)
1142             refresh /= info->vscan;
1143
1144         mode->base.refresh = refresh;
1145         mode->mode_info = *info;
1146
1147         if (info->type & DRM_MODE_TYPE_PREFERRED)
1148                 mode->base.flags |= WL_OUTPUT_MODE_PREFERRED;
1149
1150         wl_list_insert(output->base.mode_list.prev, &mode->base.link);
1151
1152         return 0;
1153 }
1154
1155 static int
1156 drm_subpixel_to_wayland(int drm_value)
1157 {
1158         switch (drm_value) {
1159         default:
1160         case DRM_MODE_SUBPIXEL_UNKNOWN:
1161                 return WL_OUTPUT_SUBPIXEL_UNKNOWN;
1162         case DRM_MODE_SUBPIXEL_NONE:
1163                 return WL_OUTPUT_SUBPIXEL_NONE;
1164         case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
1165                 return WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB;
1166         case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
1167                 return WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR;
1168         case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
1169                 return WL_OUTPUT_SUBPIXEL_VERTICAL_RGB;
1170         case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
1171                 return WL_OUTPUT_SUBPIXEL_VERTICAL_BGR;
1172         }
1173 }
1174
1175 static void
1176 sprite_handle_buffer_destroy(struct wl_listener *listener, void *data)
1177 {
1178         struct drm_sprite *sprite =
1179                 container_of(listener, struct drm_sprite,
1180                              destroy_listener);
1181         struct drm_compositor *compositor = sprite->compositor;
1182
1183         sprite->surface = NULL;
1184         drmModeRmFB(compositor->drm.fd, sprite->fb_id);
1185         sprite->fb_id = 0;
1186 }
1187
1188 static void
1189 sprite_handle_pending_buffer_destroy(struct wl_listener *listener, void *data)
1190 {
1191         struct drm_sprite *sprite =
1192                 container_of(listener, struct drm_sprite,
1193                              pending_destroy_listener);
1194         struct drm_compositor *compositor = sprite->compositor;
1195
1196         sprite->pending_surface = NULL;
1197         drmModeRmFB(compositor->drm.fd, sprite->pending_fb_id);
1198         sprite->pending_fb_id = 0;
1199 }
1200
1201 /* returns a value between 0-255 range, where higher is brighter */
1202 static uint32_t
1203 drm_get_backlight(struct drm_output *output)
1204 {
1205         long brightness, max_brightness, norm;
1206
1207         brightness = backlight_get_brightness(output->backlight);
1208         max_brightness = backlight_get_max_brightness(output->backlight);
1209
1210         /* convert it on a scale of 0 to 255 */
1211         norm = (brightness * 255)/(max_brightness);
1212
1213         return (uint32_t) norm;
1214 }
1215
1216 /* values accepted are between 0-255 range */
1217 static void
1218 drm_set_backlight(struct weston_output *output_base, uint32_t value)
1219 {
1220         struct drm_output *output = (struct drm_output *) output_base;
1221         long max_brightness, new_brightness;
1222
1223         if (!output->backlight)
1224                 return;
1225
1226         if (value > 255)
1227                 return;
1228
1229         max_brightness = backlight_get_max_brightness(output->backlight);
1230
1231         /* get denormalized value */
1232         new_brightness = (value * max_brightness) / 255;
1233
1234         backlight_set_brightness(output->backlight, new_brightness);
1235 }
1236
1237 static drmModePropertyPtr
1238 drm_get_prop(int fd, drmModeConnectorPtr connector, const char *name)
1239 {
1240         drmModePropertyPtr props;
1241         int i;
1242
1243         for (i = 0; i < connector->count_props; i++) {
1244                 props = drmModeGetProperty(fd, connector->props[i]);
1245                 if (!props)
1246                         continue;
1247
1248                 if (!strcmp(props->name, name))
1249                         return props;
1250
1251                 drmModeFreeProperty(props);
1252         }
1253
1254         return NULL;
1255 }
1256
1257 static void
1258 drm_set_dpms(struct weston_output *output_base, enum dpms_enum level)
1259 {
1260         struct drm_output *output = (struct drm_output *) output_base;
1261         struct weston_compositor *ec = output_base->compositor;
1262         struct drm_compositor *c = (struct drm_compositor *) ec;
1263         drmModeConnectorPtr connector;
1264         drmModePropertyPtr prop;
1265
1266         connector = drmModeGetConnector(c->drm.fd, output->connector_id);
1267         if (!connector)
1268                 return;
1269
1270         prop = drm_get_prop(c->drm.fd, connector, "DPMS");
1271         if (!prop) {
1272                 drmModeFreeConnector(connector);
1273                 return;
1274         }
1275
1276         drmModeConnectorSetProperty(c->drm.fd, connector->connector_id,
1277                                     prop->prop_id, level);
1278         drmModeFreeProperty(prop);
1279         drmModeFreeConnector(connector);
1280 }
1281
1282 static const char *connector_type_names[] = {
1283         "None",
1284         "VGA",
1285         "DVI",
1286         "DVI",
1287         "DVI",
1288         "Composite",
1289         "TV",
1290         "LVDS",
1291         "CTV",
1292         "DIN",
1293         "DP",
1294         "HDMI",
1295         "HDMI",
1296         "TV",
1297         "eDP",
1298 };
1299
1300 static int
1301 find_crtc_for_connector(struct drm_compositor *ec,
1302                         drmModeRes *resources, drmModeConnector *connector)
1303 {
1304         drmModeEncoder *encoder;
1305         uint32_t possible_crtcs;
1306         int i, j;
1307
1308         for (j = 0; j < connector->count_encoders; j++) {
1309                 encoder = drmModeGetEncoder(ec->drm.fd, connector->encoders[j]);
1310                 if (encoder == NULL) {
1311                         weston_log("Failed to get encoder.\n");
1312                         return -1;
1313                 }
1314                 possible_crtcs = encoder->possible_crtcs;
1315                 drmModeFreeEncoder(encoder);
1316
1317                 for (i = 0; i < resources->count_crtcs; i++) {
1318                         if (possible_crtcs & (1 << i) &&
1319                             !(ec->crtc_allocator & (1 << resources->crtcs[i])))
1320                                 return i;
1321                 }
1322         }
1323
1324         return -1;
1325 }
1326
1327 static int
1328 create_output_for_connector(struct drm_compositor *ec,
1329                             drmModeRes *resources,
1330                             drmModeConnector *connector,
1331                             int x, int y, struct udev_device *drm_device)
1332 {
1333         struct drm_output *output;
1334         struct drm_mode *drm_mode, *next;
1335         struct weston_mode *m, *preferred, *current, *configured;
1336         struct drm_configured_output *o = NULL, *temp;
1337         drmModeEncoder *encoder;
1338         drmModeModeInfo crtc_mode;
1339         drmModeCrtc *crtc;
1340         int i, ret;
1341         char name[32];
1342         const char *type_name;
1343
1344         i = find_crtc_for_connector(ec, resources, connector);
1345         if (i < 0) {
1346                 weston_log("No usable crtc/encoder pair for connector.\n");
1347                 return -1;
1348         }
1349
1350         output = malloc(sizeof *output);
1351         if (output == NULL)
1352                 return -1;
1353
1354         memset(output, 0, sizeof *output);
1355         output->base.subpixel = drm_subpixel_to_wayland(connector->subpixel);
1356         output->base.make = "unknown";
1357         output->base.model = "unknown";
1358         wl_list_init(&output->base.mode_list);
1359
1360         if (connector->connector_type < ARRAY_LENGTH(connector_type_names))
1361                 type_name = connector_type_names[connector->connector_type];
1362         else
1363                 type_name = "UNKNOWN";
1364         snprintf(name, 32, "%s%d", type_name, connector->connector_type_id);
1365         output->name = strdup(name);
1366
1367         output->crtc_id = resources->crtcs[i];
1368         ec->crtc_allocator |= (1 << output->crtc_id);
1369         output->connector_id = connector->connector_id;
1370         ec->connector_allocator |= (1 << output->connector_id);
1371
1372         output->original_crtc = drmModeGetCrtc(ec->drm.fd, output->crtc_id);
1373
1374         /* Get the current mode on the crtc that's currently driving
1375          * this connector. */
1376         encoder = drmModeGetEncoder(ec->drm.fd, connector->encoder_id);
1377         memset(&crtc_mode, 0, sizeof crtc_mode);
1378         if (encoder != NULL) {
1379                 crtc = drmModeGetCrtc(ec->drm.fd, encoder->crtc_id);
1380                 drmModeFreeEncoder(encoder);
1381                 if (crtc == NULL)
1382                         goto err_free;
1383                 if (crtc->mode_valid)
1384                         crtc_mode = crtc->mode;
1385                 drmModeFreeCrtc(crtc);
1386         }
1387
1388         for (i = 0; i < connector->count_modes; i++) {
1389                 ret = drm_output_add_mode(output, &connector->modes[i]);
1390                 if (ret)
1391                         goto err_free;
1392         }
1393
1394         preferred = NULL;
1395         current = NULL;
1396         configured = NULL;
1397
1398         wl_list_for_each(temp, &configured_output_list, link) {
1399                 if (strcmp(temp->name, output->name) == 0) {
1400                         weston_log("%s mode \"%s\" in config\n",
1401                                                         temp->name, temp->mode);
1402                         o = temp;
1403                         break;
1404                 }
1405         }
1406
1407         if (o && strcmp("off", o->mode) == 0) {
1408                 weston_log("Disabling output %s\n", o->name);
1409
1410                 drmModeSetCrtc(ec->drm.fd, output->crtc_id,
1411                                                         0, 0, 0, 0, 0, NULL);
1412                 goto err_free;
1413         }
1414
1415         wl_list_for_each(drm_mode, &output->base.mode_list, base.link) {
1416                 if (o && o->width == drm_mode->base.width &&
1417                         o->height == drm_mode->base.height &&
1418                         o->config == OUTPUT_CONFIG_MODE)
1419                         configured = &drm_mode->base;
1420                 if (!memcmp(&crtc_mode, &drm_mode->mode_info, sizeof crtc_mode))
1421                         current = &drm_mode->base;
1422                 if (drm_mode->base.flags & WL_OUTPUT_MODE_PREFERRED)
1423                         preferred = &drm_mode->base;
1424         }
1425
1426         if (o && o->config == OUTPUT_CONFIG_MODELINE) {
1427                 ret = drm_output_add_mode(output, &o->crtc_mode);
1428                 if (ret)
1429                         goto err_free;
1430                 configured = container_of(output->base.mode_list.prev,
1431                                        struct weston_mode, link);
1432                 current = configured;
1433         }
1434
1435         if (current == NULL && crtc_mode.clock != 0) {
1436                 ret = drm_output_add_mode(output, &crtc_mode);
1437                 if (ret)
1438                         goto err_free;
1439                 current = container_of(output->base.mode_list.prev,
1440                                        struct weston_mode, link);
1441         }
1442
1443         if (o && o->config == OUTPUT_CONFIG_CURRENT)
1444                 configured = current;
1445
1446         if (option_current_mode && current)
1447                 output->base.current = current;
1448         else if (configured)
1449                 output->base.current = configured;
1450         else if (preferred)
1451                 output->base.current = preferred;
1452         else if (current)
1453                 output->base.current = current;
1454
1455         if (output->base.current == NULL) {
1456                 weston_log("no available modes for %s\n", output->name);
1457                 goto err_free;
1458         }
1459
1460         output->base.current->flags |= WL_OUTPUT_MODE_CURRENT;
1461
1462         output->surface = gbm_surface_create(ec->gbm,
1463                                              output->base.current->width,
1464                                              output->base.current->height,
1465                                              GBM_FORMAT_XRGB8888,
1466                                              GBM_BO_USE_SCANOUT |
1467                                              GBM_BO_USE_RENDERING);
1468         if (!output->surface) {
1469                 weston_log("failed to create gbm surface\n");
1470                 goto err_free;
1471         }
1472
1473         output->egl_surface =
1474                 eglCreateWindowSurface(ec->base.egl_display,
1475                                        ec->base.egl_config,
1476                                        output->surface,
1477                                        NULL);
1478         if (output->egl_surface == EGL_NO_SURFACE) {
1479                 weston_log("failed to create egl surface\n");
1480                 goto err_surface;
1481         }
1482
1483         output->cursor_bo[0] =
1484                 gbm_bo_create(ec->gbm, 64, 64, GBM_FORMAT_ARGB8888,
1485                               GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
1486         output->cursor_bo[1] =
1487                 gbm_bo_create(ec->gbm, 64, 64, GBM_FORMAT_ARGB8888,
1488                               GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
1489
1490         output->backlight = backlight_init(drm_device,
1491                                            connector->connector_type);
1492         if (output->backlight) {
1493                 output->base.set_backlight = drm_set_backlight;
1494                 output->base.backlight_current = drm_get_backlight(output);
1495         }
1496
1497         weston_output_init(&output->base, &ec->base, x, y,
1498                            connector->mmWidth, connector->mmHeight,
1499                            WL_OUTPUT_FLIPPED);
1500
1501         wl_list_insert(ec->base.output_list.prev, &output->base.link);
1502
1503         output->base.origin = output->base.current;
1504         output->base.repaint = drm_output_repaint;
1505         output->base.destroy = drm_output_destroy;
1506         output->base.assign_planes = drm_assign_planes;
1507         output->base.set_dpms = drm_set_dpms;
1508         output->base.switch_mode = drm_output_switch_mode;
1509
1510         weston_plane_init(&output->cursor_plane, 0, 0);
1511         weston_plane_init(&output->fb_plane, 0, 0);
1512
1513         weston_log("Output %s, (connector %d, crtc %d)\n",
1514                    output->name, output->connector_id, output->crtc_id);
1515         wl_list_for_each(m, &output->base.mode_list, link)
1516                 weston_log_continue("  mode %dx%d@%.1f%s%s%s\n",
1517                                     m->width, m->height, m->refresh / 1000.0,
1518                                     m->flags & WL_OUTPUT_MODE_PREFERRED ?
1519                                     ", preferred" : "",
1520                                     m->flags & WL_OUTPUT_MODE_CURRENT ?
1521                                     ", current" : "",
1522                                     connector->count_modes == 0 ?
1523                                     ", built-in" : "");
1524
1525         return 0;
1526
1527 err_surface:
1528         gbm_surface_destroy(output->surface);
1529 err_free:
1530         wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
1531                                                         base.link) {
1532                 wl_list_remove(&drm_mode->base.link);
1533                 free(drm_mode);
1534         }
1535
1536         drmModeFreeCrtc(output->original_crtc);
1537         ec->crtc_allocator &= ~(1 << output->crtc_id);
1538         ec->connector_allocator &= ~(1 << output->connector_id);
1539         free(output->name);
1540         free(output);
1541
1542         return -1;
1543 }
1544
1545 static void
1546 create_sprites(struct drm_compositor *ec)
1547 {
1548         struct drm_sprite *sprite;
1549         drmModePlaneRes *plane_res;
1550         drmModePlane *plane;
1551         uint32_t i;
1552
1553         plane_res = drmModeGetPlaneResources(ec->drm.fd);
1554         if (!plane_res) {
1555                 weston_log("failed to get plane resources: %s\n",
1556                         strerror(errno));
1557                 return;
1558         }
1559
1560         for (i = 0; i < plane_res->count_planes; i++) {
1561                 plane = drmModeGetPlane(ec->drm.fd, plane_res->planes[i]);
1562                 if (!plane)
1563                         continue;
1564
1565                 sprite = malloc(sizeof(*sprite) + ((sizeof(uint32_t)) *
1566                                                    plane->count_formats));
1567                 if (!sprite) {
1568                         weston_log("%s: out of memory\n",
1569                                 __func__);
1570                         free(plane);
1571                         continue;
1572                 }
1573
1574                 memset(sprite, 0, sizeof *sprite);
1575
1576                 sprite->possible_crtcs = plane->possible_crtcs;
1577                 sprite->plane_id = plane->plane_id;
1578                 sprite->surface = NULL;
1579                 sprite->pending_surface = NULL;
1580                 sprite->fb_id = 0;
1581                 sprite->pending_fb_id = 0;
1582                 sprite->destroy_listener.notify = sprite_handle_buffer_destroy;
1583                 sprite->pending_destroy_listener.notify =
1584                         sprite_handle_pending_buffer_destroy;
1585                 sprite->compositor = ec;
1586                 sprite->count_formats = plane->count_formats;
1587                 memcpy(sprite->formats, plane->formats,
1588                        plane->count_formats * sizeof(plane->formats[0]));
1589                 drmModeFreePlane(plane);
1590                 weston_plane_init(&sprite->plane, 0, 0);
1591
1592                 wl_list_insert(&ec->sprite_list, &sprite->link);
1593         }
1594
1595         free(plane_res->planes);
1596         free(plane_res);
1597 }
1598
1599 static void
1600 destroy_sprites(struct drm_compositor *compositor)
1601 {
1602         struct drm_sprite *sprite, *next;
1603         struct drm_output *output;
1604
1605         output = container_of(compositor->base.output_list.next,
1606                               struct drm_output, base.link);
1607
1608         wl_list_for_each_safe(sprite, next, &compositor->sprite_list, link) {
1609                 drmModeSetPlane(compositor->drm.fd,
1610                                 sprite->plane_id,
1611                                 output->crtc_id, 0, 0,
1612                                 0, 0, 0, 0, 0, 0, 0, 0);
1613                 drmModeRmFB(compositor->drm.fd, sprite->fb_id);
1614                 weston_plane_release(&sprite->plane);
1615                 free(sprite);
1616         }
1617 }
1618
1619 static int
1620 create_outputs(struct drm_compositor *ec, uint32_t option_connector,
1621                struct udev_device *drm_device)
1622 {
1623         drmModeConnector *connector;
1624         drmModeRes *resources;
1625         int i;
1626         int x = 0, y = 0;
1627
1628         resources = drmModeGetResources(ec->drm.fd);
1629         if (!resources) {
1630                 weston_log("drmModeGetResources failed\n");
1631                 return -1;
1632         }
1633
1634         ec->crtcs = calloc(resources->count_crtcs, sizeof(uint32_t));
1635         if (!ec->crtcs) {
1636                 drmModeFreeResources(resources);
1637                 return -1;
1638         }
1639
1640         ec->num_crtcs = resources->count_crtcs;
1641         memcpy(ec->crtcs, resources->crtcs, sizeof(uint32_t) * ec->num_crtcs);
1642
1643         for (i = 0; i < resources->count_connectors; i++) {
1644                 connector = drmModeGetConnector(ec->drm.fd,
1645                                                 resources->connectors[i]);
1646                 if (connector == NULL)
1647                         continue;
1648
1649                 if (connector->connection == DRM_MODE_CONNECTED &&
1650                     (option_connector == 0 ||
1651                      connector->connector_id == option_connector)) {
1652                         if (create_output_for_connector(ec, resources,
1653                                                         connector, x, y,
1654                                                         drm_device) < 0) {
1655                                 drmModeFreeConnector(connector);
1656                                 continue;
1657                         }
1658
1659                         x += container_of(ec->base.output_list.prev,
1660                                           struct weston_output,
1661                                           link)->current->width;
1662                 }
1663
1664                 drmModeFreeConnector(connector);
1665         }
1666
1667         if (wl_list_empty(&ec->base.output_list)) {
1668                 weston_log("No currently active connector found.\n");
1669                 drmModeFreeResources(resources);
1670                 return -1;
1671         }
1672
1673         drmModeFreeResources(resources);
1674
1675         return 0;
1676 }
1677
1678 static void
1679 update_outputs(struct drm_compositor *ec, struct udev_device *drm_device)
1680 {
1681         drmModeConnector *connector;
1682         drmModeRes *resources;
1683         struct drm_output *output, *next;
1684         int x = 0, y = 0;
1685         int x_offset = 0, y_offset = 0;
1686         uint32_t connected = 0, disconnects = 0;
1687         int i;
1688
1689         resources = drmModeGetResources(ec->drm.fd);
1690         if (!resources) {
1691                 weston_log("drmModeGetResources failed\n");
1692                 return;
1693         }
1694
1695         /* collect new connects */
1696         for (i = 0; i < resources->count_connectors; i++) {
1697                 int connector_id = resources->connectors[i];
1698
1699                 connector = drmModeGetConnector(ec->drm.fd, connector_id);
1700                 if (connector == NULL)
1701                         continue;
1702
1703                 if (connector->connection != DRM_MODE_CONNECTED) {
1704                         drmModeFreeConnector(connector);
1705                         continue;
1706                 }
1707
1708                 connected |= (1 << connector_id);
1709
1710                 if (!(ec->connector_allocator & (1 << connector_id))) {
1711                         struct weston_output *last =
1712                                 container_of(ec->base.output_list.prev,
1713                                              struct weston_output, link);
1714
1715                         /* XXX: not yet needed, we die with 0 outputs */
1716                         if (!wl_list_empty(&ec->base.output_list))
1717                                 x = last->x + last->current->width;
1718                         else
1719                                 x = 0;
1720                         y = 0;
1721                         create_output_for_connector(ec, resources,
1722                                                     connector, x, y,
1723                                                     drm_device);
1724                         weston_log("connector %d connected\n", connector_id);
1725
1726                 }
1727                 drmModeFreeConnector(connector);
1728         }
1729         drmModeFreeResources(resources);
1730
1731         disconnects = ec->connector_allocator & ~connected;
1732         if (disconnects) {
1733                 wl_list_for_each_safe(output, next, &ec->base.output_list,
1734                                       base.link) {
1735                         if (x_offset != 0 || y_offset != 0) {
1736                                 weston_output_move(&output->base,
1737                                                  output->base.x - x_offset,
1738                                                  output->base.y - y_offset);
1739                         }
1740
1741                         if (disconnects & (1 << output->connector_id)) {
1742                                 disconnects &= ~(1 << output->connector_id);
1743                                 weston_log("connector %d disconnected\n",
1744                                        output->connector_id);
1745                                 x_offset += output->base.current->width;
1746                                 drm_output_destroy(&output->base);
1747                         }
1748                 }
1749         }
1750
1751         /* FIXME: handle zero outputs, without terminating */   
1752         if (ec->connector_allocator == 0)
1753                 wl_display_terminate(ec->base.wl_display);
1754 }
1755
1756 static int
1757 udev_event_is_hotplug(struct drm_compositor *ec, struct udev_device *device)
1758 {
1759         const char *sysnum;
1760         const char *val;
1761
1762         sysnum = udev_device_get_sysnum(device);
1763         if (!sysnum || atoi(sysnum) != ec->drm.id)
1764                 return 0;
1765
1766         val = udev_device_get_property_value(device, "HOTPLUG");
1767         if (!val)
1768                 return 0;
1769
1770         return strcmp(val, "1") == 0;
1771 }
1772
1773 static int
1774 udev_drm_event(int fd, uint32_t mask, void *data)
1775 {
1776         struct drm_compositor *ec = data;
1777         struct udev_device *event;
1778
1779         event = udev_monitor_receive_device(ec->udev_monitor);
1780
1781         if (udev_event_is_hotplug(ec, event))
1782                 update_outputs(ec, event);
1783
1784         udev_device_unref(event);
1785
1786         return 1;
1787 }
1788
1789 static void
1790 drm_restore(struct weston_compositor *ec)
1791 {
1792         struct drm_compositor *d = (struct drm_compositor *) ec;
1793
1794         if (weston_launcher_drm_set_master(&d->base, d->drm.fd, 0) < 0)
1795                 weston_log("failed to drop master: %m\n");
1796         tty_reset(d->tty);
1797 }
1798
1799 static const char default_seat[] = "seat0";
1800
1801 static void
1802 device_added(struct udev_device *udev_device, struct drm_seat *master)
1803 {
1804         struct weston_compositor *c;
1805         struct evdev_input_device *device;
1806         const char *devnode;
1807         const char *device_seat;
1808         int fd;
1809
1810         device_seat = udev_device_get_property_value(udev_device, "ID_SEAT");
1811         if (!device_seat)
1812                 device_seat = default_seat;
1813
1814         if (strcmp(device_seat, master->seat_id))
1815                 return;
1816
1817         c = master->base.compositor;
1818         devnode = udev_device_get_devnode(udev_device);
1819
1820         /* Use non-blocking mode so that we can loop on read on
1821          * evdev_input_device_data() until all events on the fd are
1822          * read.  mtdev_get() also expects this. */
1823         fd = weston_launcher_open(c, devnode, O_RDWR | O_NONBLOCK);
1824         if (fd < 0) {
1825                 weston_log("opening input device '%s' failed.\n", devnode);
1826                 return;
1827         }
1828
1829         device = evdev_input_device_create(&master->base, devnode, fd);
1830         if (!device) {
1831                 close(fd);
1832                 weston_log("not using input device '%s'.\n", devnode);
1833                 return;
1834         }
1835
1836         wl_list_insert(master->devices_list.prev, &device->link);
1837 }
1838
1839 static void
1840 evdev_add_devices(struct udev *udev, struct weston_seat *seat_base)
1841 {
1842         struct drm_seat *seat = (struct drm_seat *) seat_base;
1843         struct udev_enumerate *e;
1844         struct udev_list_entry *entry;
1845         struct udev_device *device;
1846         const char *path, *sysname;
1847
1848         e = udev_enumerate_new(udev);
1849         udev_enumerate_add_match_subsystem(e, "input");
1850         udev_enumerate_scan_devices(e);
1851         udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
1852                 path = udev_list_entry_get_name(entry);
1853                 device = udev_device_new_from_syspath(udev, path);
1854
1855                 sysname = udev_device_get_sysname(device);
1856                 if (strncmp("event", sysname, 5) != 0) {
1857                         udev_device_unref(device);
1858                         continue;
1859                 }
1860
1861                 device_added(device, seat);
1862
1863                 udev_device_unref(device);
1864         }
1865         udev_enumerate_unref(e);
1866
1867         evdev_notify_keyboard_focus(&seat->base, &seat->devices_list);
1868
1869         if (wl_list_empty(&seat->devices_list)) {
1870                 weston_log(
1871                         "warning: no input devices on entering Weston. "
1872                         "Possible causes:\n"
1873                         "\t- no permissions to read /dev/input/event*\n"
1874                         "\t- seats misconfigured "
1875                         "(Weston backend option 'seat', "
1876                         "udev device property ID_SEAT)\n");
1877         }
1878 }
1879
1880 static int
1881 evdev_udev_handler(int fd, uint32_t mask, void *data)
1882 {
1883         struct drm_seat *seat = data;
1884         struct udev_device *udev_device;
1885         struct evdev_input_device *device, *next;
1886         const char *action;
1887         const char *devnode;
1888
1889         udev_device = udev_monitor_receive_device(seat->udev_monitor);
1890         if (!udev_device)
1891                 return 1;
1892
1893         action = udev_device_get_action(udev_device);
1894         if (!action)
1895                 goto out;
1896
1897         if (strncmp("event", udev_device_get_sysname(udev_device), 5) != 0)
1898                 goto out;
1899
1900         if (!strcmp(action, "add")) {
1901                 device_added(udev_device, seat);
1902         }
1903         else if (!strcmp(action, "remove")) {
1904                 devnode = udev_device_get_devnode(udev_device);
1905                 wl_list_for_each_safe(device, next, &seat->devices_list, link)
1906                         if (!strcmp(device->devnode, devnode)) {
1907                                 weston_log("input device %s, %s removed\n",
1908                                            device->devname, device->devnode);
1909                                 evdev_input_device_destroy(device);
1910                                 break;
1911                         }
1912         }
1913
1914 out:
1915         udev_device_unref(udev_device);
1916
1917         return 0;
1918 }
1919
1920 static int
1921 evdev_enable_udev_monitor(struct udev *udev, struct weston_seat *seat_base)
1922 {
1923         struct drm_seat *master = (struct drm_seat *) seat_base;
1924         struct wl_event_loop *loop;
1925         struct weston_compositor *c = master->base.compositor;
1926         int fd;
1927
1928         master->udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
1929         if (!master->udev_monitor) {
1930                 weston_log("udev: failed to create the udev monitor\n");
1931                 return 0;
1932         }
1933
1934         udev_monitor_filter_add_match_subsystem_devtype(master->udev_monitor,
1935                         "input", NULL);
1936
1937         if (udev_monitor_enable_receiving(master->udev_monitor)) {
1938                 weston_log("udev: failed to bind the udev monitor\n");
1939                 udev_monitor_unref(master->udev_monitor);
1940                 return 0;
1941         }
1942
1943         loop = wl_display_get_event_loop(c->wl_display);
1944         fd = udev_monitor_get_fd(master->udev_monitor);
1945         master->udev_monitor_source =
1946                 wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
1947                                      evdev_udev_handler, master);
1948         if (!master->udev_monitor_source) {
1949                 udev_monitor_unref(master->udev_monitor);
1950                 return 0;
1951         }
1952
1953         return 1;
1954 }
1955
1956 static void
1957 evdev_disable_udev_monitor(struct weston_seat *seat_base)
1958 {
1959         struct drm_seat *seat = (struct drm_seat *) seat_base;
1960
1961         if (!seat->udev_monitor)
1962                 return;
1963
1964         udev_monitor_unref(seat->udev_monitor);
1965         seat->udev_monitor = NULL;
1966         wl_event_source_remove(seat->udev_monitor_source);
1967         seat->udev_monitor_source = NULL;
1968 }
1969
1970 static void
1971 drm_led_update(struct weston_seat *seat_base, enum weston_led leds)
1972 {
1973         struct drm_seat *seat = (struct drm_seat *) seat_base;
1974
1975         evdev_led_update(&seat->devices_list, leds);
1976 }
1977
1978 static void
1979 evdev_input_create(struct weston_compositor *c, struct udev *udev,
1980                    const char *seat_id)
1981 {
1982         struct drm_seat *seat;
1983
1984         seat = malloc(sizeof *seat);
1985         if (seat == NULL)
1986                 return;
1987
1988         memset(seat, 0, sizeof *seat);
1989         weston_seat_init(&seat->base, c);
1990         seat->base.led_update = drm_led_update;
1991
1992         wl_list_init(&seat->devices_list);
1993         seat->seat_id = strdup(seat_id);
1994         if (!evdev_enable_udev_monitor(udev, &seat->base)) {
1995                 free(seat->seat_id);
1996                 free(seat);
1997                 return;
1998         }
1999
2000         evdev_add_devices(udev, &seat->base);
2001
2002         c->seat = &seat->base;
2003 }
2004
2005 static void
2006 evdev_remove_devices(struct weston_seat *seat_base)
2007 {
2008         struct drm_seat *seat = (struct drm_seat *) seat_base;
2009         struct evdev_input_device *device, *next;
2010
2011         wl_list_for_each_safe(device, next, &seat->devices_list, link)
2012                 evdev_input_device_destroy(device);
2013
2014         if (seat->base.seat.keyboard)
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                 weston_log("entering VT\n");
2104                 compositor->focus = 1;
2105                 if (weston_launcher_drm_set_master(&ec->base, ec->drm.fd, 1)) {
2106                         weston_log("failed to set master: %m\n");
2107                         wl_display_terminate(compositor->wl_display);
2108                 }
2109                 compositor->state = ec->prev_state;
2110                 drm_compositor_set_modes(ec);
2111                 weston_compositor_damage_all(compositor);
2112                 wl_list_for_each(seat, &compositor->seat_list, link) {
2113                         evdev_add_devices(ec->udev, seat);
2114                         evdev_enable_udev_monitor(ec->udev, seat);
2115                 }
2116                 break;
2117         case TTY_LEAVE_VT:
2118                 weston_log("leaving VT\n");
2119                 wl_list_for_each(seat, &compositor->seat_list, link) {
2120                         evdev_disable_udev_monitor(seat);
2121                         evdev_remove_devices(seat);
2122                 }
2123
2124                 compositor->focus = 0;
2125                 ec->prev_state = compositor->state;
2126                 compositor->state = WESTON_COMPOSITOR_SLEEPING;
2127
2128                 /* If we have a repaint scheduled (either from a
2129                  * pending pageflip or the idle handler), make sure we
2130                  * cancel that so we don't try to pageflip when we're
2131                  * vt switched away.  The SLEEPING state will prevent
2132                  * further attemps at repainting.  When we switch
2133                  * back, we schedule a repaint, which will process
2134                  * pending frame callbacks. */
2135
2136                 wl_list_for_each(output, &ec->base.output_list, base.link) {
2137                         output->base.repaint_needed = 0;
2138                         drmModeSetCursor(ec->drm.fd, output->crtc_id, 0, 0, 0);
2139                 }
2140
2141                 output = container_of(ec->base.output_list.next,
2142                                       struct drm_output, base.link);
2143
2144                 wl_list_for_each(sprite, &ec->sprite_list, link)
2145                         drmModeSetPlane(ec->drm.fd,
2146                                         sprite->plane_id,
2147                                         output->crtc_id, 0, 0,
2148                                         0, 0, 0, 0, 0, 0, 0, 0);
2149
2150                 if (weston_launcher_drm_set_master(&ec->base, ec->drm.fd, 0) < 0)
2151                         weston_log("failed to drop master: %m\n");
2152
2153                 break;
2154         };
2155 }
2156
2157 static void
2158 switch_vt_binding(struct wl_seat *seat, uint32_t time, uint32_t key, void *data)
2159 {
2160         struct drm_compositor *ec = data;
2161
2162         tty_activate_vt(ec->tty, key - KEY_F1 + 1);
2163 }
2164
2165 static struct weston_compositor *
2166 drm_compositor_create(struct wl_display *display,
2167                       int connector, const char *seat, int tty,
2168                       int argc, char *argv[], const char *config_file)
2169 {
2170         struct drm_compositor *ec;
2171         struct udev_enumerate *e;
2172         struct udev_list_entry *entry;
2173         struct udev_device *device, *drm_device;
2174         const char *path, *device_seat;
2175         struct wl_event_loop *loop;
2176         struct weston_seat *weston_seat, *next;
2177         uint32_t key;
2178
2179         weston_log("initializing drm backend\n");
2180
2181         ec = malloc(sizeof *ec);
2182         if (ec == NULL)
2183                 return NULL;
2184         memset(ec, 0, sizeof *ec);
2185
2186         if (weston_compositor_init(&ec->base, display, argc, argv,
2187                                    config_file) < 0) {
2188                 weston_log("weston_compositor_init failed\n");
2189                 goto err_base;
2190         }
2191
2192         ec->udev = udev_new();
2193         if (ec->udev == NULL) {
2194                 weston_log("failed to initialize udev context\n");
2195                 goto err_compositor;
2196         }
2197
2198         ec->base.wl_display = display;
2199         ec->tty = tty_create(&ec->base, vt_func, tty);
2200         if (!ec->tty) {
2201                 weston_log("failed to initialize tty\n");
2202                 goto err_udev;
2203         }
2204
2205         e = udev_enumerate_new(ec->udev);
2206         udev_enumerate_add_match_subsystem(e, "drm");
2207         udev_enumerate_add_match_sysname(e, "card[0-9]*");
2208
2209         udev_enumerate_scan_devices(e);
2210         drm_device = NULL;
2211         udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
2212                 path = udev_list_entry_get_name(entry);
2213                 device = udev_device_new_from_syspath(ec->udev, path);
2214                 device_seat =
2215                         udev_device_get_property_value(device, "ID_SEAT");
2216                 if (!device_seat)
2217                         device_seat = default_seat;
2218                 if (strcmp(device_seat, seat) == 0) {
2219                         drm_device = device;
2220                         break;
2221                 }
2222                 udev_device_unref(device);
2223         }
2224
2225         if (drm_device == NULL) {
2226                 weston_log("no drm device found\n");
2227                 goto err_udev_enum;
2228         }
2229
2230         if (init_egl(ec, drm_device) < 0) {
2231                 weston_log("failed to initialize egl\n");
2232                 goto err_udev_dev;
2233         }
2234
2235         ec->base.destroy = drm_destroy;
2236         ec->base.restore = drm_restore;
2237
2238         ec->base.focus = 1;
2239
2240         ec->prev_state = WESTON_COMPOSITOR_ACTIVE;
2241
2242         if (weston_compositor_init_gl(&ec->base) < 0)
2243                 goto err_egl;
2244
2245         for (key = KEY_F1; key < KEY_F9; key++)
2246                 weston_compositor_add_key_binding(&ec->base, key,
2247                                                   MODIFIER_CTRL | MODIFIER_ALT,
2248                                                   switch_vt_binding, ec);
2249
2250         wl_list_init(&ec->sprite_list);
2251         create_sprites(ec);
2252
2253         if (create_outputs(ec, connector, drm_device) < 0) {
2254                 weston_log("failed to create output for %s\n", path);
2255                 goto err_sprite;
2256         }
2257
2258         path = NULL;
2259
2260         evdev_input_create(&ec->base, ec->udev, seat);
2261
2262         loop = wl_display_get_event_loop(ec->base.wl_display);
2263         ec->drm_source =
2264                 wl_event_loop_add_fd(loop, ec->drm.fd,
2265                                      WL_EVENT_READABLE, on_drm_input, ec);
2266
2267         ec->udev_monitor = udev_monitor_new_from_netlink(ec->udev, "udev");
2268         if (ec->udev_monitor == NULL) {
2269                 weston_log("failed to intialize udev monitor\n");
2270                 goto err_drm_source;
2271         }
2272         udev_monitor_filter_add_match_subsystem_devtype(ec->udev_monitor,
2273                                                         "drm", NULL);
2274         ec->udev_drm_source =
2275                 wl_event_loop_add_fd(loop,
2276                                      udev_monitor_get_fd(ec->udev_monitor),
2277                                      WL_EVENT_READABLE, udev_drm_event, ec);
2278
2279         if (udev_monitor_enable_receiving(ec->udev_monitor) < 0) {
2280                 weston_log("failed to enable udev-monitor receiving\n");
2281                 goto err_udev_monitor;
2282         }
2283
2284         udev_device_unref(drm_device);
2285         udev_enumerate_unref(e);
2286
2287         return &ec->base;
2288
2289 err_udev_monitor:
2290         wl_event_source_remove(ec->udev_drm_source);
2291         udev_monitor_unref(ec->udev_monitor);
2292 err_drm_source:
2293         wl_event_source_remove(ec->drm_source);
2294         wl_list_for_each_safe(weston_seat, next, &ec->base.seat_list, link)
2295                 evdev_input_destroy(weston_seat);
2296 err_sprite:
2297         destroy_sprites(ec);
2298 err_egl:
2299         eglMakeCurrent(ec->base.egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
2300                        EGL_NO_CONTEXT);
2301         eglTerminate(ec->base.egl_display);
2302         eglReleaseThread();
2303         gbm_device_destroy(ec->gbm);
2304 err_udev_dev:
2305         udev_device_unref(drm_device);
2306 err_udev_enum:
2307         udev_enumerate_unref(e);
2308         tty_destroy(ec->tty);
2309 err_udev:
2310         udev_unref(ec->udev);
2311 err_compositor:
2312         weston_compositor_shutdown(&ec->base);
2313 err_base:
2314         free(ec);
2315         return NULL;
2316 }
2317
2318 static int
2319 set_sync_flags(drmModeModeInfo *mode, char *hsync, char *vsync)
2320 {
2321         mode->flags = 0;
2322
2323         if (strcmp(hsync, "+hsync") == 0)
2324                 mode->flags |= DRM_MODE_FLAG_PHSYNC;
2325         else if (strcmp(hsync, "-hsync") == 0)
2326                 mode->flags |= DRM_MODE_FLAG_NHSYNC;
2327         else
2328                 return -1;
2329
2330         if (strcmp(vsync, "+vsync") == 0)
2331                 mode->flags |= DRM_MODE_FLAG_PVSYNC;
2332         else if (strcmp(vsync, "-vsync") == 0)
2333                 mode->flags |= DRM_MODE_FLAG_NVSYNC;
2334         else
2335                 return -1;
2336
2337         return 0;
2338 }
2339
2340 static int
2341 check_for_modeline(struct drm_configured_output *output)
2342 {
2343         drmModeModeInfo mode;
2344         char hsync[16];
2345         char vsync[16];
2346         char mode_name[16];
2347         float fclock;
2348
2349         mode.type = DRM_MODE_TYPE_USERDEF;
2350         mode.hskew = 0;
2351         mode.vscan = 0;
2352         mode.vrefresh = 0;
2353
2354         if (sscanf(output_mode, "%f %hd %hd %hd %hd %hd %hd %hd %hd %s %s",
2355                                                 &fclock, &mode.hdisplay,
2356                                                 &mode.hsync_start,
2357                                                 &mode.hsync_end, &mode.htotal,
2358                                                 &mode.vdisplay,
2359                                                 &mode.vsync_start,
2360                                                 &mode.vsync_end, &mode.vtotal,
2361                                                 hsync, vsync) == 11) {
2362                 if (set_sync_flags(&mode, hsync, vsync))
2363                         return -1;
2364
2365                 sprintf(mode_name, "%dx%d", mode.hdisplay, mode.vdisplay);
2366                 strcpy(mode.name, mode_name);
2367
2368                 mode.clock = fclock * 1000;
2369         } else
2370                 return -1;
2371
2372         output->crtc_mode = mode;
2373
2374         return 0;
2375 }
2376
2377 static void
2378 output_section_done(void *data)
2379 {
2380         struct drm_configured_output *output;
2381
2382         output = malloc(sizeof *output);
2383
2384         if (!output || !output_name || !output_mode) {
2385                 free(output_name);
2386                 output_name = NULL;
2387                 free(output_mode);
2388                 output_mode = NULL;
2389                 return;
2390         }
2391
2392         output->config = OUTPUT_CONFIG_INVALID;
2393         output->name = output_name;
2394         output->mode = output_mode;
2395
2396         if (strcmp(output_mode, "off") == 0)
2397                 output->config = OUTPUT_CONFIG_OFF;
2398         else if (strcmp(output_mode, "preferred") == 0)
2399                 output->config = OUTPUT_CONFIG_PREFERRED;
2400         else if (strcmp(output_mode, "current") == 0)
2401                 output->config = OUTPUT_CONFIG_CURRENT;
2402         else if (sscanf(output_mode, "%dx%d", &output->width, &output->height) == 2)
2403                 output->config = OUTPUT_CONFIG_MODE;
2404         else if (check_for_modeline(output) == 0)
2405                 output->config = OUTPUT_CONFIG_MODELINE;
2406
2407         if (output->config != OUTPUT_CONFIG_INVALID)
2408                 wl_list_insert(&configured_output_list, &output->link);
2409         else {
2410                 weston_log("Invalid mode \"%s\" for output %s\n",
2411                                                 output_mode, output_name);
2412                 drm_free_configured_output(output);
2413         }
2414 }
2415
2416 WL_EXPORT struct weston_compositor *
2417 backend_init(struct wl_display *display, int argc, char *argv[],
2418              const char *config_file)
2419 {
2420         int connector = 0, tty = 0;
2421         const char *seat = default_seat;
2422
2423         const struct weston_option drm_options[] = {
2424                 { WESTON_OPTION_INTEGER, "connector", 0, &connector },
2425                 { WESTON_OPTION_STRING, "seat", 0, &seat },
2426                 { WESTON_OPTION_INTEGER, "tty", 0, &tty },
2427                 { WESTON_OPTION_BOOLEAN, "current-mode", 0, &option_current_mode },
2428         };
2429
2430         parse_options(drm_options, ARRAY_LENGTH(drm_options), argc, argv);
2431
2432         wl_list_init(&configured_output_list);
2433
2434         const struct config_key drm_config_keys[] = {
2435                 { "name", CONFIG_KEY_STRING, &output_name },
2436                 { "mode", CONFIG_KEY_STRING, &output_mode },
2437         };
2438
2439         const struct config_section config_section[] = {
2440                 { "output", drm_config_keys,
2441                 ARRAY_LENGTH(drm_config_keys), output_section_done },
2442         };
2443
2444         parse_config_file(config_file, config_section,
2445                                 ARRAY_LENGTH(config_section), NULL);
2446
2447         return drm_compositor_create(display, connector, seat, tty, argc, argv,
2448                                      config_file);
2449 }