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