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