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