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