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