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