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