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