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