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