compositor: add WESTON_COMPOSITOR_OFFSCREEN state
[platform/upstream/weston.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_rect(&r, 0, 0,
676                                           es->geometry.width,
677                                           es->geometry.height);
678                 pixman_region32_subtract(&r, &r, &es->opaque);
679
680                 if (!pixman_region32_not_empty(&r))
681                         format = GBM_FORMAT_XRGB8888;
682
683                 pixman_region32_fini(&r);
684         }
685
686         for (i = 0; i < s->count_formats; i++)
687                 if (s->formats[i] == format)
688                         return format;
689
690         return 0;
691 }
692
693 static int
694 drm_surface_transform_supported(struct weston_surface *es)
695 {
696         return !es->transform.enabled ||
697                 (es->transform.matrix.type < WESTON_MATRIX_TRANSFORM_ROTATE);
698 }
699
700 static struct weston_plane *
701 drm_output_prepare_overlay_surface(struct weston_output *output_base,
702                                    struct weston_surface *es)
703 {
704         struct weston_compositor *ec = output_base->compositor;
705         struct drm_compositor *c =(struct drm_compositor *) ec;
706         struct drm_sprite *s;
707         int found = 0;
708         struct gbm_bo *bo;
709         pixman_region32_t dest_rect, src_rect;
710         pixman_box32_t *box, tbox;
711         uint32_t format;
712         wl_fixed_t sx1, sy1, sx2, sy2;
713
714         if (c->gbm == NULL)
715                 return NULL;
716
717         if (es->buffer_transform != output_base->transform)
718                 return NULL;
719
720         if (c->sprites_are_broken)
721                 return NULL;
722
723         if (es->output_mask != (1u << output_base->id))
724                 return NULL;
725
726         if (es->buffer_ref.buffer == NULL)
727                 return NULL;
728
729         if (es->alpha != 1.0f)
730                 return NULL;
731
732         if (wl_buffer_is_shm(es->buffer_ref.buffer))
733                 return NULL;
734
735         if (!drm_surface_transform_supported(es))
736                 return NULL;
737
738         wl_list_for_each(s, &c->sprite_list, link) {
739                 if (!drm_sprite_crtc_supported(output_base, s->possible_crtcs))
740                         continue;
741
742                 if (!s->next) {
743                         found = 1;
744                         break;
745                 }
746         }
747
748         /* No sprites available */
749         if (!found)
750                 return NULL;
751
752         bo = gbm_bo_import(c->gbm, GBM_BO_IMPORT_WL_BUFFER,
753                            es->buffer_ref.buffer, GBM_BO_USE_SCANOUT);
754         if (!bo)
755                 return NULL;
756
757         format = drm_output_check_sprite_format(s, es, bo);
758         if (format == 0) {
759                 gbm_bo_destroy(bo);
760                 return NULL;
761         }
762
763         s->next = drm_fb_get_from_bo(bo, c, format);
764         if (!s->next) {
765                 gbm_bo_destroy(bo);
766                 return NULL;
767         }
768
769         drm_fb_set_buffer(s->next, es->buffer_ref.buffer);
770
771         box = pixman_region32_extents(&es->transform.boundingbox);
772         s->plane.x = box->x1;
773         s->plane.y = box->y1;
774
775         /*
776          * Calculate the source & dest rects properly based on actual
777          * position (note the caller has called weston_surface_update_transform()
778          * for us already).
779          */
780         pixman_region32_init(&dest_rect);
781         pixman_region32_intersect(&dest_rect, &es->transform.boundingbox,
782                                   &output_base->region);
783         pixman_region32_translate(&dest_rect, -output_base->x, -output_base->y);
784         box = pixman_region32_extents(&dest_rect);
785         tbox = weston_transformed_rect(output_base->width,
786                                        output_base->height,
787                                        output_base->transform, *box);
788         s->dest_x = tbox.x1;
789         s->dest_y = tbox.y1;
790         s->dest_w = tbox.x2 - tbox.x1;
791         s->dest_h = tbox.y2 - tbox.y1;
792         pixman_region32_fini(&dest_rect);
793
794         pixman_region32_init(&src_rect);
795         pixman_region32_intersect(&src_rect, &es->transform.boundingbox,
796                                   &output_base->region);
797         box = pixman_region32_extents(&src_rect);
798
799         weston_surface_from_global_fixed(es,
800                                          wl_fixed_from_int(box->x1),
801                                          wl_fixed_from_int(box->y1),
802                                          &sx1, &sy1);
803         weston_surface_from_global_fixed(es,
804                                          wl_fixed_from_int(box->x2),
805                                          wl_fixed_from_int(box->y2),
806                                          &sx2, &sy2);
807
808         if (sx1 < 0)
809                 sx1 = 0;
810         if (sy1 < 0)
811                 sy1 = 0;
812         if (sx2 > wl_fixed_from_int(es->geometry.width))
813                 sx2 = wl_fixed_from_int(es->geometry.width);
814         if (sy2 > wl_fixed_from_int(es->geometry.height))
815                 sy2 = wl_fixed_from_int(es->geometry.height);
816
817         tbox.x1 = sx1;
818         tbox.y1 = sy1;
819         tbox.x2 = sx2;
820         tbox.y2 = sy2;
821
822         tbox = weston_transformed_rect(wl_fixed_from_int(es->geometry.width),
823                                        wl_fixed_from_int(es->geometry.height),
824                                        es->buffer_transform, tbox);
825
826         s->src_x = tbox.x1 << 8;
827         s->src_y = tbox.y1 << 8;
828         s->src_w = (tbox.x2 - tbox.x1) << 8;
829         s->src_h = (tbox.y2 - tbox.y1) << 8;
830         pixman_region32_fini(&src_rect);
831
832         return &s->plane;
833 }
834
835 static struct weston_plane *
836 drm_output_prepare_cursor_surface(struct weston_output *output_base,
837                                   struct weston_surface *es)
838 {
839         struct drm_compositor *c =
840                 (struct drm_compositor *) output_base->compositor;
841         struct drm_output *output = (struct drm_output *) output_base;
842
843         if (c->gbm == NULL)
844                 return NULL;
845         if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL)
846                 return NULL;
847         if (output->cursor_surface)
848                 return NULL;
849         if (es->output_mask != (1u << output_base->id))
850                 return NULL;
851         if (c->cursors_are_broken)
852                 return NULL;
853         if (es->buffer_ref.buffer == NULL ||
854             !wl_buffer_is_shm(es->buffer_ref.buffer) ||
855             es->geometry.width > 64 || es->geometry.height > 64)
856                 return NULL;
857
858         output->cursor_surface = es;
859
860         return &output->cursor_plane;
861 }
862
863 static void
864 drm_output_set_cursor(struct drm_output *output)
865 {
866         struct weston_surface *es = output->cursor_surface;
867         struct drm_compositor *c =
868                 (struct drm_compositor *) output->base.compositor;
869         EGLint handle, stride;
870         struct gbm_bo *bo;
871         uint32_t buf[64 * 64];
872         unsigned char *s;
873         int i, x, y;
874
875         output->cursor_surface = NULL;
876         if (es == NULL) {
877                 drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
878                 return;
879         }
880
881         if (es->buffer_ref.buffer &&
882             pixman_region32_not_empty(&output->cursor_plane.damage)) {
883                 pixman_region32_fini(&output->cursor_plane.damage);
884                 pixman_region32_init(&output->cursor_plane.damage);
885                 output->current_cursor ^= 1;
886                 bo = output->cursor_bo[output->current_cursor];
887                 memset(buf, 0, sizeof buf);
888                 stride = wl_shm_buffer_get_stride(es->buffer_ref.buffer);
889                 s = wl_shm_buffer_get_data(es->buffer_ref.buffer);
890                 for (i = 0; i < es->geometry.height; i++)
891                         memcpy(buf + i * 64, s + i * stride,
892                                es->geometry.width * 4);
893
894                 if (gbm_bo_write(bo, buf, sizeof buf) < 0)
895                         weston_log("failed update cursor: %m\n");
896
897                 handle = gbm_bo_get_handle(bo).s32;
898                 if (drmModeSetCursor(c->drm.fd,
899                                      output->crtc_id, handle, 64, 64)) {
900                         weston_log("failed to set cursor: %m\n");
901                         c->cursors_are_broken = 1;
902                 }
903         }
904
905         x = es->geometry.x - output->base.x;
906         y = es->geometry.y - output->base.y;
907         if (output->cursor_plane.x != x || output->cursor_plane.y != y) {
908                 if (drmModeMoveCursor(c->drm.fd, output->crtc_id, x, y)) {
909                         weston_log("failed to move cursor: %m\n");
910                         c->cursors_are_broken = 1;
911                 }
912
913                 output->cursor_plane.x = x;
914                 output->cursor_plane.y = y;
915         }
916 }
917
918 static void
919 drm_assign_planes(struct weston_output *output)
920 {
921         struct drm_compositor *c =
922                 (struct drm_compositor *) output->compositor;
923         struct weston_surface *es, *next;
924         pixman_region32_t overlap, surface_overlap;
925         struct weston_plane *primary, *next_plane;
926
927         /*
928          * Find a surface for each sprite in the output using some heuristics:
929          * 1) size
930          * 2) frequency of update
931          * 3) opacity (though some hw might support alpha blending)
932          * 4) clipping (this can be fixed with color keys)
933          *
934          * The idea is to save on blitting since this should save power.
935          * If we can get a large video surface on the sprite for example,
936          * the main display surface may not need to update at all, and
937          * the client buffer can be used directly for the sprite surface
938          * as we do for flipping full screen surfaces.
939          */
940         pixman_region32_init(&overlap);
941         primary = &c->base.primary_plane;
942         wl_list_for_each_safe(es, next, &c->base.surface_list, link) {
943                 /* test whether this buffer can ever go into a plane:
944                  * non-shm, or small enough to be a cursor
945                  */
946                 if ((es->buffer_ref.buffer &&
947                      !wl_buffer_is_shm(es->buffer_ref.buffer)) ||
948                     (es->geometry.width <= 64 && es->geometry.height <= 64))
949                         es->keep_buffer = 1;
950                 else
951                         es->keep_buffer = 0;
952
953                 pixman_region32_init(&surface_overlap);
954                 pixman_region32_intersect(&surface_overlap, &overlap,
955                                           &es->transform.boundingbox);
956
957                 next_plane = NULL;
958                 if (pixman_region32_not_empty(&surface_overlap))
959                         next_plane = primary;
960                 if (next_plane == NULL)
961                         next_plane = drm_output_prepare_cursor_surface(output, es);
962                 if (next_plane == NULL)
963                         next_plane = drm_output_prepare_scanout_surface(output, es);
964                 if (next_plane == NULL)
965                         next_plane = drm_output_prepare_overlay_surface(output, es);
966                 if (next_plane == NULL)
967                         next_plane = primary;
968                 weston_surface_move_to_plane(es, next_plane);
969                 if (next_plane == primary)
970                         pixman_region32_union(&overlap, &overlap,
971                                               &es->transform.boundingbox);
972
973                 pixman_region32_fini(&surface_overlap);
974         }
975         pixman_region32_fini(&overlap);
976 }
977
978 static void
979 drm_output_fini_pixman(struct drm_output *output);
980
981 static void
982 drm_output_destroy(struct weston_output *output_base)
983 {
984         struct drm_output *output = (struct drm_output *) output_base;
985         struct drm_compositor *c =
986                 (struct drm_compositor *) output->base.compositor;
987         drmModeCrtcPtr origcrtc = output->original_crtc;
988
989         if (output->backlight)
990                 backlight_destroy(output->backlight);
991
992         /* Turn off hardware cursor */
993         drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
994
995         /* Restore original CRTC state */
996         drmModeSetCrtc(c->drm.fd, origcrtc->crtc_id, origcrtc->buffer_id,
997                        origcrtc->x, origcrtc->y,
998                        &output->connector_id, 1, &origcrtc->mode);
999         drmModeFreeCrtc(origcrtc);
1000
1001         c->crtc_allocator &= ~(1 << output->crtc_id);
1002         c->connector_allocator &= ~(1 << output->connector_id);
1003
1004         if (c->use_pixman) {
1005                 drm_output_fini_pixman(output);
1006         } else {
1007                 gl_renderer_output_destroy(output_base);
1008                 gbm_surface_destroy(output->surface);
1009         }
1010
1011         weston_plane_release(&output->fb_plane);
1012         weston_plane_release(&output->cursor_plane);
1013
1014         weston_output_destroy(&output->base);
1015         wl_list_remove(&output->base.link);
1016
1017         free(output->name);
1018         free(output);
1019 }
1020
1021 static struct drm_mode *
1022 choose_mode (struct drm_output *output, struct weston_mode *target_mode)
1023 {
1024         struct drm_mode *tmp_mode = NULL, *mode;
1025
1026         if (output->base.current->width == target_mode->width && 
1027             output->base.current->height == target_mode->height &&
1028             (output->base.current->refresh == target_mode->refresh ||
1029              target_mode->refresh == 0))
1030                 return (struct drm_mode *)output->base.current;
1031
1032         wl_list_for_each(mode, &output->base.mode_list, base.link) {
1033                 if (mode->mode_info.hdisplay == target_mode->width &&
1034                     mode->mode_info.vdisplay == target_mode->height) {
1035                         if (mode->mode_info.vrefresh == target_mode->refresh || 
1036                             target_mode->refresh == 0) {
1037                                 return mode;
1038                         } else if (!tmp_mode) 
1039                                 tmp_mode = mode;
1040                 }
1041         }
1042
1043         return tmp_mode;
1044 }
1045
1046 static int
1047 drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec);
1048 static int
1049 drm_output_init_pixman(struct drm_output *output, struct drm_compositor *c);
1050
1051 static int
1052 drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mode)
1053 {
1054         struct drm_output *output;
1055         struct drm_mode *drm_mode;
1056         struct drm_compositor *ec;
1057
1058         if (output_base == NULL) {
1059                 weston_log("output is NULL.\n");
1060                 return -1;
1061         }
1062
1063         if (mode == NULL) {
1064                 weston_log("mode is NULL.\n");
1065                 return -1;
1066         }
1067
1068         ec = (struct drm_compositor *)output_base->compositor;
1069         output = (struct drm_output *)output_base;
1070         drm_mode  = choose_mode (output, mode);
1071
1072         if (!drm_mode) {
1073                 weston_log("%s, invalid resolution:%dx%d\n", __func__, mode->width, mode->height);
1074                 return -1;
1075         }
1076
1077         if (&drm_mode->base == output->base.current)
1078                 return 0;
1079
1080         output->base.current->flags = 0;
1081
1082         output->base.current = &drm_mode->base;
1083         output->base.current->flags =
1084                 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
1085
1086         /* reset rendering stuff. */
1087         drm_output_release_fb(output, output->current);
1088         drm_output_release_fb(output, output->next);
1089         output->current = output->next = NULL;
1090
1091         if (ec->use_pixman) {
1092                 drm_output_fini_pixman(output);
1093                 if (drm_output_init_pixman(output, ec) < 0) {
1094                         weston_log("failed to init output pixman state with "
1095                                    "new mode\n");
1096                         return -1;
1097                 }
1098         } else {
1099                 gl_renderer_output_destroy(&output->base);
1100                 gbm_surface_destroy(output->surface);
1101
1102                 if (drm_output_init_egl(output, ec) < 0) {
1103                         weston_log("failed to init output egl state with "
1104                                    "new mode");
1105                         return -1;
1106                 }
1107         }
1108
1109         return 0;
1110 }
1111
1112 static int
1113 on_drm_input(int fd, uint32_t mask, void *data)
1114 {
1115         drmEventContext evctx;
1116
1117         memset(&evctx, 0, sizeof evctx);
1118         evctx.version = DRM_EVENT_CONTEXT_VERSION;
1119         evctx.page_flip_handler = page_flip_handler;
1120         evctx.vblank_handler = vblank_handler;
1121         drmHandleEvent(fd, &evctx);
1122
1123         return 1;
1124 }
1125
1126 static int
1127 init_drm(struct drm_compositor *ec, struct udev_device *device)
1128 {
1129         const char *filename, *sysnum;
1130         int fd;
1131
1132         sysnum = udev_device_get_sysnum(device);
1133         if (sysnum)
1134                 ec->drm.id = atoi(sysnum);
1135         if (!sysnum || ec->drm.id < 0) {
1136                 weston_log("cannot get device sysnum\n");
1137                 return -1;
1138         }
1139
1140         filename = udev_device_get_devnode(device);
1141         fd = open(filename, O_RDWR | O_CLOEXEC);
1142         if (fd < 0) {
1143                 /* Probably permissions error */
1144                 weston_log("couldn't open %s, skipping\n",
1145                         udev_device_get_devnode(device));
1146                 return -1;
1147         }
1148
1149         weston_log("using %s\n", filename);
1150
1151         ec->drm.fd = fd;
1152
1153
1154         return 0;
1155 }
1156
1157 static int
1158 init_egl(struct drm_compositor *ec)
1159 {
1160         ec->gbm = gbm_create_device(ec->drm.fd);
1161
1162         if (!ec->gbm)
1163                 return -1;
1164
1165         if (gl_renderer_create(&ec->base, ec->gbm, gl_renderer_opaque_attribs,
1166                         NULL) < 0) {
1167                 gbm_device_destroy(ec->gbm);
1168                 return -1;
1169         }
1170
1171         return 0;
1172 }
1173
1174 static int
1175 init_pixman(struct drm_compositor *ec)
1176 {
1177         return pixman_renderer_init(&ec->base);
1178 }
1179
1180 static struct drm_mode *
1181 drm_output_add_mode(struct drm_output *output, drmModeModeInfo *info)
1182 {
1183         struct drm_mode *mode;
1184         uint64_t refresh;
1185
1186         mode = malloc(sizeof *mode);
1187         if (mode == NULL)
1188                 return NULL;
1189
1190         mode->base.flags = 0;
1191         mode->base.width = info->hdisplay;
1192         mode->base.height = info->vdisplay;
1193
1194         /* Calculate higher precision (mHz) refresh rate */
1195         refresh = (info->clock * 1000000LL / info->htotal +
1196                    info->vtotal / 2) / info->vtotal;
1197
1198         if (info->flags & DRM_MODE_FLAG_INTERLACE)
1199                 refresh *= 2;
1200         if (info->flags & DRM_MODE_FLAG_DBLSCAN)
1201                 refresh /= 2;
1202         if (info->vscan > 1)
1203             refresh /= info->vscan;
1204
1205         mode->base.refresh = refresh;
1206         mode->mode_info = *info;
1207
1208         if (info->type & DRM_MODE_TYPE_PREFERRED)
1209                 mode->base.flags |= WL_OUTPUT_MODE_PREFERRED;
1210
1211         wl_list_insert(output->base.mode_list.prev, &mode->base.link);
1212
1213         return mode;
1214 }
1215
1216 static int
1217 drm_subpixel_to_wayland(int drm_value)
1218 {
1219         switch (drm_value) {
1220         default:
1221         case DRM_MODE_SUBPIXEL_UNKNOWN:
1222                 return WL_OUTPUT_SUBPIXEL_UNKNOWN;
1223         case DRM_MODE_SUBPIXEL_NONE:
1224                 return WL_OUTPUT_SUBPIXEL_NONE;
1225         case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
1226                 return WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB;
1227         case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
1228                 return WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR;
1229         case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
1230                 return WL_OUTPUT_SUBPIXEL_VERTICAL_RGB;
1231         case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
1232                 return WL_OUTPUT_SUBPIXEL_VERTICAL_BGR;
1233         }
1234 }
1235
1236 /* returns a value between 0-255 range, where higher is brighter */
1237 static uint32_t
1238 drm_get_backlight(struct drm_output *output)
1239 {
1240         long brightness, max_brightness, norm;
1241
1242         brightness = backlight_get_brightness(output->backlight);
1243         max_brightness = backlight_get_max_brightness(output->backlight);
1244
1245         /* convert it on a scale of 0 to 255 */
1246         norm = (brightness * 255)/(max_brightness);
1247
1248         return (uint32_t) norm;
1249 }
1250
1251 /* values accepted are between 0-255 range */
1252 static void
1253 drm_set_backlight(struct weston_output *output_base, uint32_t value)
1254 {
1255         struct drm_output *output = (struct drm_output *) output_base;
1256         long max_brightness, new_brightness;
1257
1258         if (!output->backlight)
1259                 return;
1260
1261         if (value > 255)
1262                 return;
1263
1264         max_brightness = backlight_get_max_brightness(output->backlight);
1265
1266         /* get denormalized value */
1267         new_brightness = (value * max_brightness) / 255;
1268
1269         backlight_set_brightness(output->backlight, new_brightness);
1270 }
1271
1272 static drmModePropertyPtr
1273 drm_get_prop(int fd, drmModeConnectorPtr connector, const char *name)
1274 {
1275         drmModePropertyPtr props;
1276         int i;
1277
1278         for (i = 0; i < connector->count_props; i++) {
1279                 props = drmModeGetProperty(fd, connector->props[i]);
1280                 if (!props)
1281                         continue;
1282
1283                 if (!strcmp(props->name, name))
1284                         return props;
1285
1286                 drmModeFreeProperty(props);
1287         }
1288
1289         return NULL;
1290 }
1291
1292 static void
1293 drm_set_dpms(struct weston_output *output_base, enum dpms_enum level)
1294 {
1295         struct drm_output *output = (struct drm_output *) output_base;
1296         struct weston_compositor *ec = output_base->compositor;
1297         struct drm_compositor *c = (struct drm_compositor *) ec;
1298         drmModeConnectorPtr connector;
1299         drmModePropertyPtr prop;
1300
1301         connector = drmModeGetConnector(c->drm.fd, output->connector_id);
1302         if (!connector)
1303                 return;
1304
1305         prop = drm_get_prop(c->drm.fd, connector, "DPMS");
1306         if (!prop) {
1307                 drmModeFreeConnector(connector);
1308                 return;
1309         }
1310
1311         drmModeConnectorSetProperty(c->drm.fd, connector->connector_id,
1312                                     prop->prop_id, level);
1313         drmModeFreeProperty(prop);
1314         drmModeFreeConnector(connector);
1315 }
1316
1317 static const char *connector_type_names[] = {
1318         "None",
1319         "VGA",
1320         "DVI",
1321         "DVI",
1322         "DVI",
1323         "Composite",
1324         "TV",
1325         "LVDS",
1326         "CTV",
1327         "DIN",
1328         "DP",
1329         "HDMI",
1330         "HDMI",
1331         "TV",
1332         "eDP",
1333 };
1334
1335 static int
1336 find_crtc_for_connector(struct drm_compositor *ec,
1337                         drmModeRes *resources, drmModeConnector *connector)
1338 {
1339         drmModeEncoder *encoder;
1340         uint32_t possible_crtcs;
1341         int i, j;
1342
1343         for (j = 0; j < connector->count_encoders; j++) {
1344                 encoder = drmModeGetEncoder(ec->drm.fd, connector->encoders[j]);
1345                 if (encoder == NULL) {
1346                         weston_log("Failed to get encoder.\n");
1347                         return -1;
1348                 }
1349                 possible_crtcs = encoder->possible_crtcs;
1350                 drmModeFreeEncoder(encoder);
1351
1352                 for (i = 0; i < resources->count_crtcs; i++) {
1353                         if (possible_crtcs & (1 << i) &&
1354                             !(ec->crtc_allocator & (1 << resources->crtcs[i])))
1355                                 return i;
1356                 }
1357         }
1358
1359         return -1;
1360 }
1361
1362 /* Init output state that depends on gl or gbm */
1363 static int
1364 drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec)
1365 {
1366         int i, flags;
1367
1368         output->surface = gbm_surface_create(ec->gbm,
1369                                              output->base.current->width,
1370                                              output->base.current->height,
1371                                              GBM_FORMAT_XRGB8888,
1372                                              GBM_BO_USE_SCANOUT |
1373                                              GBM_BO_USE_RENDERING);
1374         if (!output->surface) {
1375                 weston_log("failed to create gbm surface\n");
1376                 return -1;
1377         }
1378
1379         if (gl_renderer_output_create(&output->base, output->surface) < 0) {
1380                 weston_log("failed to create gl renderer output state\n");
1381                 gbm_surface_destroy(output->surface);
1382                 return -1;
1383         }
1384
1385         flags = GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE;
1386
1387         for (i = 0; i < 2; i++) {
1388                 if (output->cursor_bo[i])
1389                         continue;
1390
1391                 output->cursor_bo[i] =
1392                         gbm_bo_create(ec->gbm, 64, 64, GBM_FORMAT_ARGB8888,
1393                                       flags);
1394         }
1395
1396         if (output->cursor_bo[0] == NULL || output->cursor_bo[1] == NULL) {
1397                 weston_log("cursor buffers unavailable, using gl cursors\n");
1398                 ec->cursors_are_broken = 1;
1399         }
1400
1401         return 0;
1402 }
1403
1404 static int
1405 drm_output_init_pixman(struct drm_output *output, struct drm_compositor *c)
1406 {
1407         int w = output->base.current->width;
1408         int h = output->base.current->height;
1409         unsigned int i;
1410
1411         /* FIXME error checking */
1412
1413         for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
1414                 output->dumb[i] = drm_fb_create_dumb(c, w, h);
1415                 if (!output->dumb[i])
1416                         goto err;
1417
1418                 output->image[i] =
1419                         pixman_image_create_bits(PIXMAN_x8r8g8b8, w, h,
1420                                                  output->dumb[i]->map,
1421                                                  output->dumb[i]->stride);
1422                 if (!output->image[i])
1423                         goto err;
1424         }
1425
1426         if (pixman_renderer_output_create(&output->base) < 0)
1427                 goto err;
1428
1429         pixman_region32_init_rect(&output->previous_damage,
1430                                   output->base.x, output->base.y, w, h);
1431
1432         return 0;
1433
1434 err:
1435         for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
1436                 if (output->dumb[i])
1437                         drm_fb_destroy_dumb(output->dumb[i]);
1438                 if (output->image[i])
1439                         pixman_image_unref(output->image[i]);
1440
1441                 output->dumb[i] = NULL;
1442                 output->image[i] = NULL;
1443         }
1444
1445         return -1;
1446 }
1447
1448 static void
1449 drm_output_fini_pixman(struct drm_output *output)
1450 {
1451         unsigned int i;
1452
1453         pixman_renderer_output_destroy(&output->base);
1454         pixman_region32_fini(&output->previous_damage);
1455
1456         for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
1457                 drm_fb_destroy_dumb(output->dumb[i]);
1458                 pixman_image_unref(output->image[i]);
1459                 output->dumb[i] = NULL;
1460                 output->image[i] = NULL;
1461         }
1462 }
1463
1464 static int
1465 create_output_for_connector(struct drm_compositor *ec,
1466                             drmModeRes *resources,
1467                             drmModeConnector *connector,
1468                             int x, int y, struct udev_device *drm_device)
1469 {
1470         struct drm_output *output;
1471         struct drm_mode *drm_mode, *next, *preferred, *current, *configured;
1472         struct weston_mode *m;
1473         struct drm_configured_output *o = NULL, *temp;
1474         drmModeEncoder *encoder;
1475         drmModeModeInfo crtc_mode;
1476         drmModeCrtc *crtc;
1477         int i;
1478         char name[32];
1479         const char *type_name;
1480
1481         i = find_crtc_for_connector(ec, resources, connector);
1482         if (i < 0) {
1483                 weston_log("No usable crtc/encoder pair for connector.\n");
1484                 return -1;
1485         }
1486
1487         output = malloc(sizeof *output);
1488         if (output == NULL)
1489                 return -1;
1490
1491         memset(output, 0, sizeof *output);
1492         output->base.subpixel = drm_subpixel_to_wayland(connector->subpixel);
1493         output->base.make = "unknown";
1494         output->base.model = "unknown";
1495         wl_list_init(&output->base.mode_list);
1496
1497         if (connector->connector_type < ARRAY_LENGTH(connector_type_names))
1498                 type_name = connector_type_names[connector->connector_type];
1499         else
1500                 type_name = "UNKNOWN";
1501         snprintf(name, 32, "%s%d", type_name, connector->connector_type_id);
1502         output->name = strdup(name);
1503
1504         output->crtc_id = resources->crtcs[i];
1505         output->pipe = i;
1506         ec->crtc_allocator |= (1 << output->crtc_id);
1507         output->connector_id = connector->connector_id;
1508         ec->connector_allocator |= (1 << output->connector_id);
1509
1510         output->original_crtc = drmModeGetCrtc(ec->drm.fd, output->crtc_id);
1511
1512         /* Get the current mode on the crtc that's currently driving
1513          * this connector. */
1514         encoder = drmModeGetEncoder(ec->drm.fd, connector->encoder_id);
1515         memset(&crtc_mode, 0, sizeof crtc_mode);
1516         if (encoder != NULL) {
1517                 crtc = drmModeGetCrtc(ec->drm.fd, encoder->crtc_id);
1518                 drmModeFreeEncoder(encoder);
1519                 if (crtc == NULL)
1520                         goto err_free;
1521                 if (crtc->mode_valid)
1522                         crtc_mode = crtc->mode;
1523                 drmModeFreeCrtc(crtc);
1524         }
1525
1526         for (i = 0; i < connector->count_modes; i++) {
1527                 drm_mode = drm_output_add_mode(output, &connector->modes[i]);
1528                 if (!drm_mode)
1529                         goto err_free;
1530         }
1531
1532         preferred = NULL;
1533         current = NULL;
1534         configured = NULL;
1535
1536         wl_list_for_each(temp, &configured_output_list, link) {
1537                 if (strcmp(temp->name, output->name) == 0) {
1538                         if (temp->mode)
1539                                 weston_log("%s mode \"%s\" in config\n",
1540                                                         temp->name, temp->mode);
1541                         o = temp;
1542                         break;
1543                 }
1544         }
1545
1546         if (o && o->config == OUTPUT_CONFIG_OFF) {
1547                 weston_log("Disabling output %s\n", o->name);
1548
1549                 drmModeSetCrtc(ec->drm.fd, output->crtc_id,
1550                                                         0, 0, 0, 0, 0, NULL);
1551                 goto err_free;
1552         }
1553
1554         wl_list_for_each(drm_mode, &output->base.mode_list, base.link) {
1555                 if (o && o->config == OUTPUT_CONFIG_MODE &&
1556                         o->width == drm_mode->base.width &&
1557                         o->height == drm_mode->base.height)
1558                         configured = drm_mode;
1559                 if (!memcmp(&crtc_mode, &drm_mode->mode_info, sizeof crtc_mode))
1560                         current = drm_mode;
1561                 if (drm_mode->base.flags & WL_OUTPUT_MODE_PREFERRED)
1562                         preferred = drm_mode;
1563         }
1564
1565         if (o && o->config == OUTPUT_CONFIG_MODELINE) {
1566                 configured = drm_output_add_mode(output, &o->crtc_mode);
1567                 if (!configured)
1568                         goto err_free;
1569                 current = configured;
1570         }
1571
1572         if (current == NULL && crtc_mode.clock != 0) {
1573                 current = drm_output_add_mode(output, &crtc_mode);
1574                 if (!current)
1575                         goto err_free;
1576         }
1577
1578         if (o && o->config == OUTPUT_CONFIG_CURRENT)
1579                 configured = current;
1580
1581         if (option_current_mode && current)
1582                 output->base.current = &current->base;
1583         else if (configured)
1584                 output->base.current = &configured->base;
1585         else if (preferred)
1586                 output->base.current = &preferred->base;
1587         else if (current)
1588                 output->base.current = &current->base;
1589
1590         if (output->base.current == NULL) {
1591                 weston_log("no available modes for %s\n", output->name);
1592                 goto err_free;
1593         }
1594
1595         output->base.current->flags |= WL_OUTPUT_MODE_CURRENT;
1596
1597         weston_output_init(&output->base, &ec->base, x, y,
1598                            connector->mmWidth, connector->mmHeight,
1599                            o ? o->transform : WL_OUTPUT_TRANSFORM_NORMAL);
1600
1601         if (ec->use_pixman) {
1602                 if (drm_output_init_pixman(output, ec) < 0) {
1603                         weston_log("Failed to init output pixman state\n");
1604                         goto err_output;
1605                 }
1606         } else if (drm_output_init_egl(output, ec) < 0) {
1607                 weston_log("Failed to init output gl state\n");
1608                 goto err_output;
1609         }
1610
1611         output->backlight = backlight_init(drm_device,
1612                                            connector->connector_type);
1613         if (output->backlight) {
1614                 output->base.set_backlight = drm_set_backlight;
1615                 output->base.backlight_current = drm_get_backlight(output);
1616         }
1617
1618         wl_list_insert(ec->base.output_list.prev, &output->base.link);
1619
1620         output->base.origin = output->base.current;
1621         output->base.repaint = drm_output_repaint;
1622         output->base.destroy = drm_output_destroy;
1623         output->base.assign_planes = drm_assign_planes;
1624         output->base.set_dpms = drm_set_dpms;
1625         output->base.switch_mode = drm_output_switch_mode;
1626
1627         weston_plane_init(&output->cursor_plane, 0, 0);
1628         weston_plane_init(&output->fb_plane, 0, 0);
1629
1630         weston_compositor_stack_plane(&ec->base, &output->cursor_plane, NULL);
1631         weston_compositor_stack_plane(&ec->base, &output->fb_plane,
1632                                       &ec->base.primary_plane);
1633
1634         weston_log("Output %s, (connector %d, crtc %d)\n",
1635                    output->name, output->connector_id, output->crtc_id);
1636         wl_list_for_each(m, &output->base.mode_list, link)
1637                 weston_log_continue("  mode %dx%d@%.1f%s%s%s\n",
1638                                     m->width, m->height, m->refresh / 1000.0,
1639                                     m->flags & WL_OUTPUT_MODE_PREFERRED ?
1640                                     ", preferred" : "",
1641                                     m->flags & WL_OUTPUT_MODE_CURRENT ?
1642                                     ", current" : "",
1643                                     connector->count_modes == 0 ?
1644                                     ", built-in" : "");
1645
1646         return 0;
1647
1648 err_output:
1649         weston_output_destroy(&output->base);
1650 err_free:
1651         wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
1652                                                         base.link) {
1653                 wl_list_remove(&drm_mode->base.link);
1654                 free(drm_mode);
1655         }
1656
1657         drmModeFreeCrtc(output->original_crtc);
1658         ec->crtc_allocator &= ~(1 << output->crtc_id);
1659         ec->connector_allocator &= ~(1 << output->connector_id);
1660         free(output->name);
1661         free(output);
1662
1663         return -1;
1664 }
1665
1666 static void
1667 create_sprites(struct drm_compositor *ec)
1668 {
1669         struct drm_sprite *sprite;
1670         drmModePlaneRes *plane_res;
1671         drmModePlane *plane;
1672         uint32_t i;
1673
1674         plane_res = drmModeGetPlaneResources(ec->drm.fd);
1675         if (!plane_res) {
1676                 weston_log("failed to get plane resources: %s\n",
1677                         strerror(errno));
1678                 return;
1679         }
1680
1681         for (i = 0; i < plane_res->count_planes; i++) {
1682                 plane = drmModeGetPlane(ec->drm.fd, plane_res->planes[i]);
1683                 if (!plane)
1684                         continue;
1685
1686                 sprite = malloc(sizeof(*sprite) + ((sizeof(uint32_t)) *
1687                                                    plane->count_formats));
1688                 if (!sprite) {
1689                         weston_log("%s: out of memory\n",
1690                                 __func__);
1691                         free(plane);
1692                         continue;
1693                 }
1694
1695                 memset(sprite, 0, sizeof *sprite);
1696
1697                 sprite->possible_crtcs = plane->possible_crtcs;
1698                 sprite->plane_id = plane->plane_id;
1699                 sprite->current = NULL;
1700                 sprite->next = NULL;
1701                 sprite->compositor = ec;
1702                 sprite->count_formats = plane->count_formats;
1703                 memcpy(sprite->formats, plane->formats,
1704                        plane->count_formats * sizeof(plane->formats[0]));
1705                 drmModeFreePlane(plane);
1706                 weston_plane_init(&sprite->plane, 0, 0);
1707                 weston_compositor_stack_plane(&ec->base, &sprite->plane,
1708                                               &ec->base.primary_plane);
1709
1710                 wl_list_insert(&ec->sprite_list, &sprite->link);
1711         }
1712
1713         free(plane_res->planes);
1714         free(plane_res);
1715 }
1716
1717 static void
1718 destroy_sprites(struct drm_compositor *compositor)
1719 {
1720         struct drm_sprite *sprite, *next;
1721         struct drm_output *output;
1722
1723         output = container_of(compositor->base.output_list.next,
1724                               struct drm_output, base.link);
1725
1726         wl_list_for_each_safe(sprite, next, &compositor->sprite_list, link) {
1727                 drmModeSetPlane(compositor->drm.fd,
1728                                 sprite->plane_id,
1729                                 output->crtc_id, 0, 0,
1730                                 0, 0, 0, 0, 0, 0, 0, 0);
1731                 drm_output_release_fb(output, sprite->current);
1732                 drm_output_release_fb(output, sprite->next);
1733                 weston_plane_release(&sprite->plane);
1734                 free(sprite);
1735         }
1736 }
1737
1738 static int
1739 create_outputs(struct drm_compositor *ec, uint32_t option_connector,
1740                struct udev_device *drm_device)
1741 {
1742         drmModeConnector *connector;
1743         drmModeRes *resources;
1744         int i;
1745         int x = 0, y = 0;
1746
1747         resources = drmModeGetResources(ec->drm.fd);
1748         if (!resources) {
1749                 weston_log("drmModeGetResources failed\n");
1750                 return -1;
1751         }
1752
1753         ec->crtcs = calloc(resources->count_crtcs, sizeof(uint32_t));
1754         if (!ec->crtcs) {
1755                 drmModeFreeResources(resources);
1756                 return -1;
1757         }
1758
1759         ec->min_width  = resources->min_width;
1760         ec->max_width  = resources->max_width;
1761         ec->min_height = resources->min_height;
1762         ec->max_height = resources->max_height;
1763
1764         ec->num_crtcs = resources->count_crtcs;
1765         memcpy(ec->crtcs, resources->crtcs, sizeof(uint32_t) * ec->num_crtcs);
1766
1767         for (i = 0; i < resources->count_connectors; i++) {
1768                 connector = drmModeGetConnector(ec->drm.fd,
1769                                                 resources->connectors[i]);
1770                 if (connector == NULL)
1771                         continue;
1772
1773                 if (connector->connection == DRM_MODE_CONNECTED &&
1774                     (option_connector == 0 ||
1775                      connector->connector_id == option_connector)) {
1776                         if (create_output_for_connector(ec, resources,
1777                                                         connector, x, y,
1778                                                         drm_device) < 0) {
1779                                 drmModeFreeConnector(connector);
1780                                 continue;
1781                         }
1782
1783                         x += container_of(ec->base.output_list.prev,
1784                                           struct weston_output,
1785                                           link)->width;
1786                 }
1787
1788                 drmModeFreeConnector(connector);
1789         }
1790
1791         if (wl_list_empty(&ec->base.output_list)) {
1792                 weston_log("No currently active connector found.\n");
1793                 drmModeFreeResources(resources);
1794                 return -1;
1795         }
1796
1797         drmModeFreeResources(resources);
1798
1799         return 0;
1800 }
1801
1802 static void
1803 update_outputs(struct drm_compositor *ec, struct udev_device *drm_device)
1804 {
1805         drmModeConnector *connector;
1806         drmModeRes *resources;
1807         struct drm_output *output, *next;
1808         int x = 0, y = 0;
1809         int x_offset = 0, y_offset = 0;
1810         uint32_t connected = 0, disconnects = 0;
1811         int i;
1812
1813         resources = drmModeGetResources(ec->drm.fd);
1814         if (!resources) {
1815                 weston_log("drmModeGetResources failed\n");
1816                 return;
1817         }
1818
1819         /* collect new connects */
1820         for (i = 0; i < resources->count_connectors; i++) {
1821                 int connector_id = resources->connectors[i];
1822
1823                 connector = drmModeGetConnector(ec->drm.fd, connector_id);
1824                 if (connector == NULL)
1825                         continue;
1826
1827                 if (connector->connection != DRM_MODE_CONNECTED) {
1828                         drmModeFreeConnector(connector);
1829                         continue;
1830                 }
1831
1832                 connected |= (1 << connector_id);
1833
1834                 if (!(ec->connector_allocator & (1 << connector_id))) {
1835                         struct weston_output *last =
1836                                 container_of(ec->base.output_list.prev,
1837                                              struct weston_output, link);
1838
1839                         /* XXX: not yet needed, we die with 0 outputs */
1840                         if (!wl_list_empty(&ec->base.output_list))
1841                                 x = last->x + last->width;
1842                         else
1843                                 x = 0;
1844                         y = 0;
1845                         create_output_for_connector(ec, resources,
1846                                                     connector, x, y,
1847                                                     drm_device);
1848                         weston_log("connector %d connected\n", connector_id);
1849
1850                 }
1851                 drmModeFreeConnector(connector);
1852         }
1853         drmModeFreeResources(resources);
1854
1855         disconnects = ec->connector_allocator & ~connected;
1856         if (disconnects) {
1857                 wl_list_for_each_safe(output, next, &ec->base.output_list,
1858                                       base.link) {
1859                         if (x_offset != 0 || y_offset != 0) {
1860                                 weston_output_move(&output->base,
1861                                                  output->base.x - x_offset,
1862                                                  output->base.y - y_offset);
1863                         }
1864
1865                         if (disconnects & (1 << output->connector_id)) {
1866                                 disconnects &= ~(1 << output->connector_id);
1867                                 weston_log("connector %d disconnected\n",
1868                                        output->connector_id);
1869                                 x_offset += output->base.width;
1870                                 drm_output_destroy(&output->base);
1871                         }
1872                 }
1873         }
1874
1875         /* FIXME: handle zero outputs, without terminating */   
1876         if (ec->connector_allocator == 0)
1877                 wl_display_terminate(ec->base.wl_display);
1878 }
1879
1880 static int
1881 udev_event_is_hotplug(struct drm_compositor *ec, struct udev_device *device)
1882 {
1883         const char *sysnum;
1884         const char *val;
1885
1886         sysnum = udev_device_get_sysnum(device);
1887         if (!sysnum || atoi(sysnum) != ec->drm.id)
1888                 return 0;
1889
1890         val = udev_device_get_property_value(device, "HOTPLUG");
1891         if (!val)
1892                 return 0;
1893
1894         return strcmp(val, "1") == 0;
1895 }
1896
1897 static int
1898 udev_drm_event(int fd, uint32_t mask, void *data)
1899 {
1900         struct drm_compositor *ec = data;
1901         struct udev_device *event;
1902
1903         event = udev_monitor_receive_device(ec->udev_monitor);
1904
1905         if (udev_event_is_hotplug(ec, event))
1906                 update_outputs(ec, event);
1907
1908         udev_device_unref(event);
1909
1910         return 1;
1911 }
1912
1913 static void
1914 drm_restore(struct weston_compositor *ec)
1915 {
1916         struct drm_compositor *d = (struct drm_compositor *) ec;
1917
1918         if (weston_launcher_drm_set_master(&d->base, d->drm.fd, 0) < 0)
1919                 weston_log("failed to drop master: %m\n");
1920         tty_reset(d->tty);
1921 }
1922
1923 static void
1924 drm_free_configured_output(struct drm_configured_output *output)
1925 {
1926         free(output->name);
1927         free(output->mode);
1928         free(output);
1929 }
1930
1931 static void
1932 drm_destroy(struct weston_compositor *ec)
1933 {
1934         struct drm_compositor *d = (struct drm_compositor *) ec;
1935         struct udev_seat *seat, *next;
1936         struct drm_configured_output *o, *n;
1937
1938         wl_list_for_each_safe(seat, next, &ec->seat_list, base.link)
1939                 udev_seat_destroy(seat);
1940         wl_list_for_each_safe(o, n, &configured_output_list, link)
1941                 drm_free_configured_output(o);
1942
1943         wl_event_source_remove(d->udev_drm_source);
1944         wl_event_source_remove(d->drm_source);
1945
1946         weston_compositor_shutdown(ec);
1947
1948         ec->renderer->destroy(ec);
1949
1950         destroy_sprites(d);
1951
1952         if (d->gbm)
1953                 gbm_device_destroy(d->gbm);
1954
1955         if (weston_launcher_drm_set_master(&d->base, d->drm.fd, 0) < 0)
1956                 weston_log("failed to drop master: %m\n");
1957         tty_destroy(d->tty);
1958
1959         free(d);
1960 }
1961
1962 static void
1963 drm_compositor_set_modes(struct drm_compositor *compositor)
1964 {
1965         struct drm_output *output;
1966         struct drm_mode *drm_mode;
1967         int ret;
1968
1969         wl_list_for_each(output, &compositor->base.output_list, base.link) {
1970                 if (!output->current) {
1971                         /* If something that would cause the output to
1972                          * switch mode happened while in another vt, we
1973                          * might not have a current drm_fb. In that case,
1974                          * schedule a repaint and let drm_output_repaint
1975                          * handle setting the mode. */
1976                         weston_output_schedule_repaint(&output->base);
1977                         continue;
1978                 }
1979
1980                 drm_mode = (struct drm_mode *) output->base.current;
1981                 ret = drmModeSetCrtc(compositor->drm.fd, output->crtc_id,
1982                                      output->current->fb_id, 0, 0,
1983                                      &output->connector_id, 1,
1984                                      &drm_mode->mode_info);
1985                 if (ret < 0) {
1986                         weston_log(
1987                                 "failed to set mode %dx%d for output at %d,%d: %m\n",
1988                                 drm_mode->base.width, drm_mode->base.height, 
1989                                 output->base.x, output->base.y);
1990                 }
1991         }
1992 }
1993
1994 static void
1995 vt_func(struct weston_compositor *compositor, int event)
1996 {
1997         struct drm_compositor *ec = (struct drm_compositor *) compositor;
1998         struct udev_seat *seat;
1999         struct drm_sprite *sprite;
2000         struct drm_output *output;
2001
2002         switch (event) {
2003         case TTY_ENTER_VT:
2004                 weston_log("entering VT\n");
2005                 compositor->focus = 1;
2006                 if (weston_launcher_drm_set_master(&ec->base, ec->drm.fd, 1)) {
2007                         weston_log("failed to set master: %m\n");
2008                         wl_display_terminate(compositor->wl_display);
2009                 }
2010                 compositor->state = ec->prev_state;
2011                 drm_compositor_set_modes(ec);
2012                 weston_compositor_damage_all(compositor);
2013                 wl_list_for_each(seat, &compositor->seat_list, base.link)
2014                         udev_seat_enable(seat, ec->udev);
2015                 break;
2016         case TTY_LEAVE_VT:
2017                 weston_log("leaving VT\n");
2018                 wl_list_for_each(seat, &compositor->seat_list, base.link)
2019                         udev_seat_disable(seat);
2020
2021                 compositor->focus = 0;
2022                 ec->prev_state = compositor->state;
2023                 weston_compositor_offscreen(compositor);
2024
2025                 /* If we have a repaint scheduled (either from a
2026                  * pending pageflip or the idle handler), make sure we
2027                  * cancel that so we don't try to pageflip when we're
2028                  * vt switched away.  The OFFSCREEN state will prevent
2029                  * further attemps at repainting.  When we switch
2030                  * back, we schedule a repaint, which will process
2031                  * pending frame callbacks. */
2032
2033                 wl_list_for_each(output, &ec->base.output_list, base.link) {
2034                         output->base.repaint_needed = 0;
2035                         drmModeSetCursor(ec->drm.fd, output->crtc_id, 0, 0, 0);
2036                 }
2037
2038                 output = container_of(ec->base.output_list.next,
2039                                       struct drm_output, base.link);
2040
2041                 wl_list_for_each(sprite, &ec->sprite_list, link)
2042                         drmModeSetPlane(ec->drm.fd,
2043                                         sprite->plane_id,
2044                                         output->crtc_id, 0, 0,
2045                                         0, 0, 0, 0, 0, 0, 0, 0);
2046
2047                 if (weston_launcher_drm_set_master(&ec->base, ec->drm.fd, 0) < 0)
2048                         weston_log("failed to drop master: %m\n");
2049
2050                 break;
2051         };
2052 }
2053
2054 static void
2055 switch_vt_binding(struct wl_seat *seat, uint32_t time, uint32_t key, void *data)
2056 {
2057         struct drm_compositor *ec = data;
2058
2059         tty_activate_vt(ec->tty, key - KEY_F1 + 1);
2060 }
2061
2062 /*
2063  * Find primary GPU
2064  * Some systems may have multiple DRM devices attached to a single seat. This
2065  * function loops over all devices and tries to find a PCI device with the
2066  * boot_vga sysfs attribute set to 1.
2067  * If no such device is found, the first DRM device reported by udev is used.
2068  */
2069 static struct udev_device*
2070 find_primary_gpu(struct drm_compositor *ec, const char *seat)
2071 {
2072         struct udev_enumerate *e;
2073         struct udev_list_entry *entry;
2074         const char *path, *device_seat, *id;
2075         struct udev_device *device, *drm_device, *pci;
2076
2077         e = udev_enumerate_new(ec->udev);
2078         udev_enumerate_add_match_subsystem(e, "drm");
2079         udev_enumerate_add_match_sysname(e, "card[0-9]*");
2080
2081         udev_enumerate_scan_devices(e);
2082         drm_device = NULL;
2083         udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
2084                 path = udev_list_entry_get_name(entry);
2085                 device = udev_device_new_from_syspath(ec->udev, path);
2086                 if (!device)
2087                         continue;
2088                 device_seat = udev_device_get_property_value(device, "ID_SEAT");
2089                 if (!device_seat)
2090                         device_seat = default_seat;
2091                 if (strcmp(device_seat, seat)) {
2092                         udev_device_unref(device);
2093                         continue;
2094                 }
2095
2096                 pci = udev_device_get_parent_with_subsystem_devtype(device,
2097                                                                 "pci", NULL);
2098                 if (pci) {
2099                         id = udev_device_get_sysattr_value(pci, "boot_vga");
2100                         if (id && !strcmp(id, "1")) {
2101                                 if (drm_device)
2102                                         udev_device_unref(drm_device);
2103                                 drm_device = device;
2104                                 break;
2105                         }
2106                 }
2107
2108                 if (!drm_device)
2109                         drm_device = device;
2110                 else
2111                         udev_device_unref(device);
2112         }
2113
2114         udev_enumerate_unref(e);
2115         return drm_device;
2116 }
2117
2118 static void
2119 planes_binding(struct wl_seat *seat, uint32_t time, uint32_t key, void *data)
2120 {
2121         struct drm_compositor *c = data;
2122
2123         switch (key) {
2124         case KEY_C:
2125                 c->cursors_are_broken ^= 1;
2126                 break;
2127         case KEY_V:
2128                 c->sprites_are_broken ^= 1;
2129                 break;
2130         case KEY_O:
2131                 c->sprites_hidden ^= 1;
2132                 break;
2133         default:
2134                 break;
2135         }
2136 }
2137
2138 static struct weston_compositor *
2139 drm_compositor_create(struct wl_display *display,
2140                       int connector, const char *seat, int tty, int pixman,
2141                       int *argc, char *argv[], const char *config_file)
2142 {
2143         struct drm_compositor *ec;
2144         struct udev_device *drm_device;
2145         struct wl_event_loop *loop;
2146         struct udev_seat *udev_seat, *next;
2147         const char *path;
2148         uint32_t key;
2149
2150         weston_log("initializing drm backend\n");
2151
2152         ec = malloc(sizeof *ec);
2153         if (ec == NULL)
2154                 return NULL;
2155         memset(ec, 0, sizeof *ec);
2156
2157         /* KMS support for sprites is not complete yet, so disable the
2158          * functionality for now. */
2159         ec->sprites_are_broken = 1;
2160
2161         ec->use_pixman = pixman;
2162
2163         if (weston_compositor_init(&ec->base, display, argc, argv,
2164                                    config_file) < 0) {
2165                 weston_log("%s failed\n", __func__);
2166                 goto err_base;
2167         }
2168
2169         /* Check if we run drm-backend using weston-launch */
2170         if (ec->base.launcher_sock == -1) {
2171                 weston_log("fatal: drm backend should be run "
2172                            "using weston-launch binary\n");
2173                 goto err_compositor;
2174         }
2175
2176         ec->udev = udev_new();
2177         if (ec->udev == NULL) {
2178                 weston_log("failed to initialize udev context\n");
2179                 goto err_compositor;
2180         }
2181
2182         ec->base.wl_display = display;
2183         ec->tty = tty_create(&ec->base, vt_func, tty);
2184         if (!ec->tty) {
2185                 weston_log("failed to initialize tty\n");
2186                 goto err_udev;
2187         }
2188
2189         drm_device = find_primary_gpu(ec, seat);
2190         if (drm_device == NULL) {
2191                 weston_log("no drm device found\n");
2192                 goto err_tty;
2193         }
2194         path = udev_device_get_syspath(drm_device);
2195
2196         if (init_drm(ec, drm_device) < 0) {
2197                 weston_log("failed to initialize kms\n");
2198                 goto err_udev_dev;
2199         }
2200
2201         if (ec->use_pixman) {
2202                 if (init_pixman(ec) < 0) {
2203                         weston_log("failed to initialize pixman renderer\n");
2204                         goto err_udev_dev;
2205                 }
2206         } else {
2207                 if (init_egl(ec) < 0) {
2208                         weston_log("failed to initialize egl\n");
2209                         goto err_udev_dev;
2210                 }
2211         }
2212
2213         ec->base.destroy = drm_destroy;
2214         ec->base.restore = drm_restore;
2215
2216         ec->base.focus = 1;
2217
2218         ec->prev_state = WESTON_COMPOSITOR_ACTIVE;
2219
2220         for (key = KEY_F1; key < KEY_F9; key++)
2221                 weston_compositor_add_key_binding(&ec->base, key,
2222                                                   MODIFIER_CTRL | MODIFIER_ALT,
2223                                                   switch_vt_binding, ec);
2224
2225         wl_list_init(&ec->sprite_list);
2226         create_sprites(ec);
2227
2228         if (create_outputs(ec, connector, drm_device) < 0) {
2229                 weston_log("failed to create output for %s\n", path);
2230                 goto err_sprite;
2231         }
2232
2233         path = NULL;
2234
2235         if (udev_seat_create(&ec->base, ec->udev, seat) == NULL) {
2236                 weston_log("failed to create input devices\n");
2237                 goto err_sprite;
2238         }
2239
2240         loop = wl_display_get_event_loop(ec->base.wl_display);
2241         ec->drm_source =
2242                 wl_event_loop_add_fd(loop, ec->drm.fd,
2243                                      WL_EVENT_READABLE, on_drm_input, ec);
2244
2245         ec->udev_monitor = udev_monitor_new_from_netlink(ec->udev, "udev");
2246         if (ec->udev_monitor == NULL) {
2247                 weston_log("failed to intialize udev monitor\n");
2248                 goto err_drm_source;
2249         }
2250         udev_monitor_filter_add_match_subsystem_devtype(ec->udev_monitor,
2251                                                         "drm", NULL);
2252         ec->udev_drm_source =
2253                 wl_event_loop_add_fd(loop,
2254                                      udev_monitor_get_fd(ec->udev_monitor),
2255                                      WL_EVENT_READABLE, udev_drm_event, ec);
2256
2257         if (udev_monitor_enable_receiving(ec->udev_monitor) < 0) {
2258                 weston_log("failed to enable udev-monitor receiving\n");
2259                 goto err_udev_monitor;
2260         }
2261
2262         udev_device_unref(drm_device);
2263
2264         weston_compositor_add_debug_binding(&ec->base, KEY_O,
2265                                             planes_binding, ec);
2266         weston_compositor_add_debug_binding(&ec->base, KEY_C,
2267                                             planes_binding, ec);
2268         weston_compositor_add_debug_binding(&ec->base, KEY_V,
2269                                             planes_binding, ec);
2270
2271         return &ec->base;
2272
2273 err_udev_monitor:
2274         wl_event_source_remove(ec->udev_drm_source);
2275         udev_monitor_unref(ec->udev_monitor);
2276 err_drm_source:
2277         wl_event_source_remove(ec->drm_source);
2278         wl_list_for_each_safe(udev_seat, next, &ec->base.seat_list, base.link)
2279                 udev_seat_destroy(udev_seat);
2280 err_sprite:
2281         ec->base.renderer->destroy(&ec->base);
2282         gbm_device_destroy(ec->gbm);
2283         destroy_sprites(ec);
2284 err_udev_dev:
2285         udev_device_unref(drm_device);
2286 err_tty:
2287         if (weston_launcher_drm_set_master(&ec->base, ec->drm.fd, 0) < 0)
2288                 weston_log("failed to drop master: %m\n");
2289         tty_destroy(ec->tty);
2290 err_udev:
2291         udev_unref(ec->udev);
2292 err_compositor:
2293         weston_compositor_shutdown(&ec->base);
2294 err_base:
2295         free(ec);
2296         return NULL;
2297 }
2298
2299 static int
2300 set_sync_flags(drmModeModeInfo *mode, char *hsync, char *vsync)
2301 {
2302         mode->flags = 0;
2303
2304         if (strcmp(hsync, "+hsync") == 0)
2305                 mode->flags |= DRM_MODE_FLAG_PHSYNC;
2306         else if (strcmp(hsync, "-hsync") == 0)
2307                 mode->flags |= DRM_MODE_FLAG_NHSYNC;
2308         else
2309                 return -1;
2310
2311         if (strcmp(vsync, "+vsync") == 0)
2312                 mode->flags |= DRM_MODE_FLAG_PVSYNC;
2313         else if (strcmp(vsync, "-vsync") == 0)
2314                 mode->flags |= DRM_MODE_FLAG_NVSYNC;
2315         else
2316                 return -1;
2317
2318         return 0;
2319 }
2320
2321 static int
2322 check_for_modeline(struct drm_configured_output *output)
2323 {
2324         drmModeModeInfo mode;
2325         char hsync[16];
2326         char vsync[16];
2327         char mode_name[16];
2328         float fclock;
2329
2330         mode.type = DRM_MODE_TYPE_USERDEF;
2331         mode.hskew = 0;
2332         mode.vscan = 0;
2333         mode.vrefresh = 0;
2334
2335         if (sscanf(output_mode, "%f %hd %hd %hd %hd %hd %hd %hd %hd %s %s",
2336                                                 &fclock, &mode.hdisplay,
2337                                                 &mode.hsync_start,
2338                                                 &mode.hsync_end, &mode.htotal,
2339                                                 &mode.vdisplay,
2340                                                 &mode.vsync_start,
2341                                                 &mode.vsync_end, &mode.vtotal,
2342                                                 hsync, vsync) == 11) {
2343                 if (set_sync_flags(&mode, hsync, vsync))
2344                         return -1;
2345
2346                 sprintf(mode_name, "%dx%d", mode.hdisplay, mode.vdisplay);
2347                 strcpy(mode.name, mode_name);
2348
2349                 mode.clock = fclock * 1000;
2350         } else
2351                 return -1;
2352
2353         output->crtc_mode = mode;
2354
2355         return 0;
2356 }
2357
2358 static void
2359 drm_output_set_transform(struct drm_configured_output *output)
2360 {
2361         if (!output_transform) {
2362                 output->transform = WL_OUTPUT_TRANSFORM_NORMAL;
2363                 return;
2364         }
2365
2366         if (!strcmp(output_transform, "normal"))
2367                 output->transform = WL_OUTPUT_TRANSFORM_NORMAL;
2368         else if (!strcmp(output_transform, "90"))
2369                 output->transform = WL_OUTPUT_TRANSFORM_90;
2370         else if (!strcmp(output_transform, "180"))
2371                 output->transform = WL_OUTPUT_TRANSFORM_180;
2372         else if (!strcmp(output_transform, "270"))
2373                 output->transform = WL_OUTPUT_TRANSFORM_270;
2374         else if (!strcmp(output_transform, "flipped"))
2375                 output->transform = WL_OUTPUT_TRANSFORM_FLIPPED;
2376         else if (!strcmp(output_transform, "flipped-90"))
2377                 output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_90;
2378         else if (!strcmp(output_transform, "flipped-180"))
2379                 output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_180;
2380         else if (!strcmp(output_transform, "flipped-270"))
2381                 output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_270;
2382         else {
2383                 weston_log("Invalid transform \"%s\" for output %s\n",
2384                                                 output_transform, output_name);
2385                 output->transform = WL_OUTPUT_TRANSFORM_NORMAL;
2386         }
2387
2388         free(output_transform);
2389         output_transform = NULL;
2390 }
2391
2392 static void
2393 output_section_done(void *data)
2394 {
2395         struct drm_configured_output *output;
2396
2397         output = malloc(sizeof *output);
2398
2399         if (!output || !output_name || (output_name[0] == 'X') ||
2400                                         (!output_mode && !output_transform)) {
2401                 free(output_name);
2402                 free(output_mode);
2403                 free(output_transform);
2404                 free(output);
2405                 output_name = NULL;
2406                 output_mode = NULL;
2407                 output_transform = NULL;
2408                 return;
2409         }
2410
2411         output->config = OUTPUT_CONFIG_INVALID;
2412         output->name = output_name;
2413         output->mode = output_mode;
2414
2415         if (output_mode) {
2416                 if (strcmp(output_mode, "off") == 0)
2417                         output->config = OUTPUT_CONFIG_OFF;
2418                 else if (strcmp(output_mode, "preferred") == 0)
2419                         output->config = OUTPUT_CONFIG_PREFERRED;
2420                 else if (strcmp(output_mode, "current") == 0)
2421                         output->config = OUTPUT_CONFIG_CURRENT;
2422                 else if (sscanf(output_mode, "%dx%d",
2423                                         &output->width, &output->height) == 2)
2424                         output->config = OUTPUT_CONFIG_MODE;
2425                 else if (check_for_modeline(output) == 0)
2426                         output->config = OUTPUT_CONFIG_MODELINE;
2427
2428                 if (output->config == OUTPUT_CONFIG_INVALID)
2429                         weston_log("Invalid mode \"%s\" for output %s\n",
2430                                                         output_mode, output_name);
2431                 output_mode = NULL;
2432         }
2433
2434         drm_output_set_transform(output);
2435
2436         wl_list_insert(&configured_output_list, &output->link);
2437
2438         if (output_transform)
2439                 free(output_transform);
2440         output_transform = NULL;
2441 }
2442
2443 WL_EXPORT struct weston_compositor *
2444 backend_init(struct wl_display *display, int *argc, char *argv[],
2445              const char *config_file)
2446 {
2447         int connector = 0, tty = 0, use_pixman = 0;
2448         const char *seat = default_seat;
2449
2450         const struct weston_option drm_options[] = {
2451                 { WESTON_OPTION_INTEGER, "connector", 0, &connector },
2452                 { WESTON_OPTION_STRING, "seat", 0, &seat },
2453                 { WESTON_OPTION_INTEGER, "tty", 0, &tty },
2454                 { WESTON_OPTION_BOOLEAN, "current-mode", 0, &option_current_mode },
2455                 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &use_pixman },
2456         };
2457
2458         parse_options(drm_options, ARRAY_LENGTH(drm_options), argc, argv);
2459
2460         wl_list_init(&configured_output_list);
2461
2462         const struct config_key drm_config_keys[] = {
2463                 { "name", CONFIG_KEY_STRING, &output_name },
2464                 { "mode", CONFIG_KEY_STRING, &output_mode },
2465                 { "transform", CONFIG_KEY_STRING, &output_transform },
2466         };
2467
2468         const struct config_section config_section[] = {
2469                 { "output", drm_config_keys,
2470                 ARRAY_LENGTH(drm_config_keys), output_section_done },
2471         };
2472
2473         parse_config_file(config_file, config_section,
2474                                 ARRAY_LENGTH(config_section), NULL);
2475
2476         return drm_compositor_create(display, connector, seat, tty, use_pixman,
2477                                      argc, argv, config_file);
2478 }