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