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