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