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