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