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