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