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