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