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