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