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