configure.ac: Auto-enable vaapi recorder, but allow overrides
[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, 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, GBM_BO_USE_SCANOUT);
826         if (!bo)
827                 return NULL;
828
829         format = drm_output_check_sprite_format(s, es, bo);
830         if (format == 0) {
831                 gbm_bo_destroy(bo);
832                 return NULL;
833         }
834
835         s->next = drm_fb_get_from_bo(bo, c, format);
836         if (!s->next) {
837                 gbm_bo_destroy(bo);
838                 return NULL;
839         }
840
841         drm_fb_set_buffer(s->next, es->buffer_ref.buffer);
842
843         box = pixman_region32_extents(&es->transform.boundingbox);
844         s->plane.x = box->x1;
845         s->plane.y = box->y1;
846
847         /*
848          * Calculate the source & dest rects properly based on actual
849          * position (note the caller has called weston_surface_update_transform()
850          * for us already).
851          */
852         pixman_region32_init(&dest_rect);
853         pixman_region32_intersect(&dest_rect, &es->transform.boundingbox,
854                                   &output_base->region);
855         pixman_region32_translate(&dest_rect, -output_base->x, -output_base->y);
856         box = pixman_region32_extents(&dest_rect);
857         tbox = weston_transformed_rect(output_base->width,
858                                        output_base->height,
859                                        output_base->transform,
860                                        output_base->scale,
861                                        *box);
862         s->dest_x = tbox.x1;
863         s->dest_y = tbox.y1;
864         s->dest_w = tbox.x2 - tbox.x1;
865         s->dest_h = tbox.y2 - tbox.y1;
866         pixman_region32_fini(&dest_rect);
867
868         pixman_region32_init(&src_rect);
869         pixman_region32_intersect(&src_rect, &es->transform.boundingbox,
870                                   &output_base->region);
871         box = pixman_region32_extents(&src_rect);
872
873         weston_surface_from_global_fixed(es,
874                                          wl_fixed_from_int(box->x1),
875                                          wl_fixed_from_int(box->y1),
876                                          &sx1, &sy1);
877         weston_surface_from_global_fixed(es,
878                                          wl_fixed_from_int(box->x2),
879                                          wl_fixed_from_int(box->y2),
880                                          &sx2, &sy2);
881
882         if (sx1 < 0)
883                 sx1 = 0;
884         if (sy1 < 0)
885                 sy1 = 0;
886         if (sx2 > wl_fixed_from_int(es->geometry.width))
887                 sx2 = wl_fixed_from_int(es->geometry.width);
888         if (sy2 > wl_fixed_from_int(es->geometry.height))
889                 sy2 = wl_fixed_from_int(es->geometry.height);
890
891         tbox.x1 = sx1;
892         tbox.y1 = sy1;
893         tbox.x2 = sx2;
894         tbox.y2 = sy2;
895
896         tbox = weston_transformed_rect(wl_fixed_from_int(es->geometry.width),
897                                        wl_fixed_from_int(es->geometry.height),
898                                        es->buffer_transform, es->buffer_scale, tbox);
899
900         s->src_x = tbox.x1 << 8;
901         s->src_y = tbox.y1 << 8;
902         s->src_w = (tbox.x2 - tbox.x1) << 8;
903         s->src_h = (tbox.y2 - tbox.y1) << 8;
904         pixman_region32_fini(&src_rect);
905
906         return &s->plane;
907 }
908
909 static struct weston_plane *
910 drm_output_prepare_cursor_surface(struct weston_output *output_base,
911                                   struct weston_surface *es)
912 {
913         struct drm_compositor *c =
914                 (struct drm_compositor *) output_base->compositor;
915         struct drm_output *output = (struct drm_output *) output_base;
916
917         if (c->gbm == NULL)
918                 return NULL;
919         if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL)
920                 return NULL;
921         if (output->cursor_surface)
922                 return NULL;
923         if (es->output_mask != (1u << output_base->id))
924                 return NULL;
925         if (c->cursors_are_broken)
926                 return NULL;
927         if (es->buffer_ref.buffer == NULL ||
928             !wl_shm_buffer_get(es->buffer_ref.buffer->resource) ||
929             es->geometry.width > 64 || es->geometry.height > 64)
930                 return NULL;
931
932         output->cursor_surface = es;
933
934         return &output->cursor_plane;
935 }
936
937 static void
938 drm_output_set_cursor(struct drm_output *output)
939 {
940         struct weston_surface *es = output->cursor_surface;
941         struct drm_compositor *c =
942                 (struct drm_compositor *) output->base.compositor;
943         EGLint handle, stride;
944         struct gbm_bo *bo;
945         uint32_t buf[64 * 64];
946         unsigned char *s;
947         int i, x, y;
948
949         output->cursor_surface = NULL;
950         if (es == NULL) {
951                 drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
952                 return;
953         }
954
955         if (es->buffer_ref.buffer &&
956             pixman_region32_not_empty(&output->cursor_plane.damage)) {
957                 pixman_region32_fini(&output->cursor_plane.damage);
958                 pixman_region32_init(&output->cursor_plane.damage);
959                 output->current_cursor ^= 1;
960                 bo = output->cursor_bo[output->current_cursor];
961                 memset(buf, 0, sizeof buf);
962                 stride = wl_shm_buffer_get_stride(es->buffer_ref.buffer->shm_buffer);
963                 s = wl_shm_buffer_get_data(es->buffer_ref.buffer->shm_buffer);
964                 for (i = 0; i < es->geometry.height; i++)
965                         memcpy(buf + i * 64, s + i * stride,
966                                es->geometry.width * 4);
967
968                 if (gbm_bo_write(bo, buf, sizeof buf) < 0)
969                         weston_log("failed update cursor: %m\n");
970
971                 handle = gbm_bo_get_handle(bo).s32;
972                 if (drmModeSetCursor(c->drm.fd,
973                                      output->crtc_id, handle, 64, 64)) {
974                         weston_log("failed to set cursor: %m\n");
975                         c->cursors_are_broken = 1;
976                 }
977         }
978
979         x = (es->geometry.x - output->base.x) * output->base.scale;
980         y = (es->geometry.y - output->base.y) * output->base.scale;
981         if (output->cursor_plane.x != x || output->cursor_plane.y != y) {
982                 if (drmModeMoveCursor(c->drm.fd, output->crtc_id, x, y)) {
983                         weston_log("failed to move cursor: %m\n");
984                         c->cursors_are_broken = 1;
985                 }
986
987                 output->cursor_plane.x = x;
988                 output->cursor_plane.y = y;
989         }
990 }
991
992 static void
993 drm_assign_planes(struct weston_output *output)
994 {
995         struct drm_compositor *c =
996                 (struct drm_compositor *) output->compositor;
997         struct weston_surface *es, *next;
998         pixman_region32_t overlap, surface_overlap;
999         struct weston_plane *primary, *next_plane;
1000
1001         /*
1002          * Find a surface for each sprite in the output using some heuristics:
1003          * 1) size
1004          * 2) frequency of update
1005          * 3) opacity (though some hw might support alpha blending)
1006          * 4) clipping (this can be fixed with color keys)
1007          *
1008          * The idea is to save on blitting since this should save power.
1009          * If we can get a large video surface on the sprite for example,
1010          * the main display surface may not need to update at all, and
1011          * the client buffer can be used directly for the sprite surface
1012          * as we do for flipping full screen surfaces.
1013          */
1014         pixman_region32_init(&overlap);
1015         primary = &c->base.primary_plane;
1016         wl_list_for_each_safe(es, next, &c->base.surface_list, link) {
1017                 /* test whether this buffer can ever go into a plane:
1018                  * non-shm, or small enough to be a cursor
1019                  */
1020                 if ((es->buffer_ref.buffer &&
1021                      !wl_shm_buffer_get(es->buffer_ref.buffer->resource)) ||
1022                     (es->geometry.width <= 64 && es->geometry.height <= 64))
1023                         es->keep_buffer = 1;
1024                 else
1025                         es->keep_buffer = 0;
1026
1027                 pixman_region32_init(&surface_overlap);
1028                 pixman_region32_intersect(&surface_overlap, &overlap,
1029                                           &es->transform.boundingbox);
1030
1031                 next_plane = NULL;
1032                 if (pixman_region32_not_empty(&surface_overlap))
1033                         next_plane = primary;
1034                 if (next_plane == NULL)
1035                         next_plane = drm_output_prepare_cursor_surface(output, es);
1036                 if (next_plane == NULL)
1037                         next_plane = drm_output_prepare_scanout_surface(output, es);
1038                 if (next_plane == NULL)
1039                         next_plane = drm_output_prepare_overlay_surface(output, es);
1040                 if (next_plane == NULL)
1041                         next_plane = primary;
1042                 weston_surface_move_to_plane(es, next_plane);
1043                 if (next_plane == primary)
1044                         pixman_region32_union(&overlap, &overlap,
1045                                               &es->transform.boundingbox);
1046
1047                 pixman_region32_fini(&surface_overlap);
1048         }
1049         pixman_region32_fini(&overlap);
1050 }
1051
1052 static void
1053 drm_output_fini_pixman(struct drm_output *output);
1054
1055 static void
1056 drm_output_destroy(struct weston_output *output_base)
1057 {
1058         struct drm_output *output = (struct drm_output *) output_base;
1059         struct drm_compositor *c =
1060                 (struct drm_compositor *) output->base.compositor;
1061         drmModeCrtcPtr origcrtc = output->original_crtc;
1062
1063         if (output->backlight)
1064                 backlight_destroy(output->backlight);
1065
1066         drmModeFreeProperty(output->dpms_prop);
1067
1068         /* Turn off hardware cursor */
1069         drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
1070
1071         /* Restore original CRTC state */
1072         drmModeSetCrtc(c->drm.fd, origcrtc->crtc_id, origcrtc->buffer_id,
1073                        origcrtc->x, origcrtc->y,
1074                        &output->connector_id, 1, &origcrtc->mode);
1075         drmModeFreeCrtc(origcrtc);
1076
1077         c->crtc_allocator &= ~(1 << output->crtc_id);
1078         c->connector_allocator &= ~(1 << output->connector_id);
1079
1080         if (c->use_pixman) {
1081                 drm_output_fini_pixman(output);
1082         } else {
1083                 gl_renderer_output_destroy(output_base);
1084                 gbm_surface_destroy(output->surface);
1085         }
1086
1087         weston_plane_release(&output->fb_plane);
1088         weston_plane_release(&output->cursor_plane);
1089
1090         weston_output_destroy(&output->base);
1091         wl_list_remove(&output->base.link);
1092
1093         free(output);
1094 }
1095
1096 static struct drm_mode *
1097 choose_mode (struct drm_output *output, struct weston_mode *target_mode)
1098 {
1099         struct drm_mode *tmp_mode = NULL, *mode;
1100
1101         if (output->base.current->width == target_mode->width && 
1102             output->base.current->height == target_mode->height &&
1103             (output->base.current->refresh == target_mode->refresh ||
1104              target_mode->refresh == 0))
1105                 return (struct drm_mode *)output->base.current;
1106
1107         wl_list_for_each(mode, &output->base.mode_list, base.link) {
1108                 if (mode->mode_info.hdisplay == target_mode->width &&
1109                     mode->mode_info.vdisplay == target_mode->height) {
1110                         if (mode->mode_info.vrefresh == target_mode->refresh || 
1111                             target_mode->refresh == 0) {
1112                                 return mode;
1113                         } else if (!tmp_mode) 
1114                                 tmp_mode = mode;
1115                 }
1116         }
1117
1118         return tmp_mode;
1119 }
1120
1121 static int
1122 drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec);
1123 static int
1124 drm_output_init_pixman(struct drm_output *output, struct drm_compositor *c);
1125
1126 static int
1127 drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mode)
1128 {
1129         struct drm_output *output;
1130         struct drm_mode *drm_mode;
1131         struct drm_compositor *ec;
1132
1133         if (output_base == NULL) {
1134                 weston_log("output is NULL.\n");
1135                 return -1;
1136         }
1137
1138         if (mode == NULL) {
1139                 weston_log("mode is NULL.\n");
1140                 return -1;
1141         }
1142
1143         ec = (struct drm_compositor *)output_base->compositor;
1144         output = (struct drm_output *)output_base;
1145         drm_mode  = choose_mode (output, mode);
1146
1147         if (!drm_mode) {
1148                 weston_log("%s, invalid resolution:%dx%d\n", __func__, mode->width, mode->height);
1149                 return -1;
1150         }
1151
1152         if (&drm_mode->base == output->base.current)
1153                 return 0;
1154
1155         output->base.current->flags = 0;
1156
1157         output->base.current = &drm_mode->base;
1158         output->base.current->flags =
1159                 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
1160
1161         /* reset rendering stuff. */
1162         drm_output_release_fb(output, output->current);
1163         drm_output_release_fb(output, output->next);
1164         output->current = output->next = NULL;
1165
1166         if (ec->use_pixman) {
1167                 drm_output_fini_pixman(output);
1168                 if (drm_output_init_pixman(output, ec) < 0) {
1169                         weston_log("failed to init output pixman state with "
1170                                    "new mode\n");
1171                         return -1;
1172                 }
1173         } else {
1174                 gl_renderer_output_destroy(&output->base);
1175                 gbm_surface_destroy(output->surface);
1176
1177                 if (drm_output_init_egl(output, ec) < 0) {
1178                         weston_log("failed to init output egl state with "
1179                                    "new mode");
1180                         return -1;
1181                 }
1182         }
1183
1184         return 0;
1185 }
1186
1187 static int
1188 on_drm_input(int fd, uint32_t mask, void *data)
1189 {
1190         drmEventContext evctx;
1191
1192         memset(&evctx, 0, sizeof evctx);
1193         evctx.version = DRM_EVENT_CONTEXT_VERSION;
1194         evctx.page_flip_handler = page_flip_handler;
1195         evctx.vblank_handler = vblank_handler;
1196         drmHandleEvent(fd, &evctx);
1197
1198         return 1;
1199 }
1200
1201 static int
1202 init_drm(struct drm_compositor *ec, struct udev_device *device)
1203 {
1204         const char *filename, *sysnum;
1205         uint64_t cap;
1206         int fd, ret;
1207
1208         sysnum = udev_device_get_sysnum(device);
1209         if (sysnum)
1210                 ec->drm.id = atoi(sysnum);
1211         if (!sysnum || ec->drm.id < 0) {
1212                 weston_log("cannot get device sysnum\n");
1213                 return -1;
1214         }
1215
1216         filename = udev_device_get_devnode(device);
1217         fd = open(filename, O_RDWR | O_CLOEXEC);
1218         if (fd < 0) {
1219                 /* Probably permissions error */
1220                 weston_log("couldn't open %s, skipping\n",
1221                         udev_device_get_devnode(device));
1222                 return -1;
1223         }
1224
1225         weston_log("using %s\n", filename);
1226
1227         ec->drm.fd = fd;
1228         ec->drm.filename = strdup(filename);
1229
1230         ret = drmGetCap(fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap);
1231         if (ret == 0 && cap == 1)
1232                 ec->clock = CLOCK_MONOTONIC;
1233         else
1234                 ec->clock = CLOCK_REALTIME;
1235
1236         return 0;
1237 }
1238
1239 static int
1240 init_egl(struct drm_compositor *ec)
1241 {
1242         ec->gbm = gbm_create_device(ec->drm.fd);
1243
1244         if (!ec->gbm)
1245                 return -1;
1246
1247         if (gl_renderer_create(&ec->base, ec->gbm, gl_renderer_opaque_attribs,
1248                         NULL) < 0) {
1249                 gbm_device_destroy(ec->gbm);
1250                 return -1;
1251         }
1252
1253         return 0;
1254 }
1255
1256 static int
1257 init_pixman(struct drm_compositor *ec)
1258 {
1259         return pixman_renderer_init(&ec->base);
1260 }
1261
1262 static struct drm_mode *
1263 drm_output_add_mode(struct drm_output *output, drmModeModeInfo *info)
1264 {
1265         struct drm_mode *mode;
1266         uint64_t refresh;
1267
1268         mode = malloc(sizeof *mode);
1269         if (mode == NULL)
1270                 return NULL;
1271
1272         mode->base.flags = 0;
1273         mode->base.width = info->hdisplay;
1274         mode->base.height = info->vdisplay;
1275
1276         /* Calculate higher precision (mHz) refresh rate */
1277         refresh = (info->clock * 1000000LL / info->htotal +
1278                    info->vtotal / 2) / info->vtotal;
1279
1280         if (info->flags & DRM_MODE_FLAG_INTERLACE)
1281                 refresh *= 2;
1282         if (info->flags & DRM_MODE_FLAG_DBLSCAN)
1283                 refresh /= 2;
1284         if (info->vscan > 1)
1285             refresh /= info->vscan;
1286
1287         mode->base.refresh = refresh;
1288         mode->mode_info = *info;
1289
1290         if (info->type & DRM_MODE_TYPE_PREFERRED)
1291                 mode->base.flags |= WL_OUTPUT_MODE_PREFERRED;
1292
1293         wl_list_insert(output->base.mode_list.prev, &mode->base.link);
1294
1295         return mode;
1296 }
1297
1298 static int
1299 drm_subpixel_to_wayland(int drm_value)
1300 {
1301         switch (drm_value) {
1302         default:
1303         case DRM_MODE_SUBPIXEL_UNKNOWN:
1304                 return WL_OUTPUT_SUBPIXEL_UNKNOWN;
1305         case DRM_MODE_SUBPIXEL_NONE:
1306                 return WL_OUTPUT_SUBPIXEL_NONE;
1307         case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
1308                 return WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB;
1309         case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
1310                 return WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR;
1311         case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
1312                 return WL_OUTPUT_SUBPIXEL_VERTICAL_RGB;
1313         case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
1314                 return WL_OUTPUT_SUBPIXEL_VERTICAL_BGR;
1315         }
1316 }
1317
1318 /* returns a value between 0-255 range, where higher is brighter */
1319 static uint32_t
1320 drm_get_backlight(struct drm_output *output)
1321 {
1322         long brightness, max_brightness, norm;
1323
1324         brightness = backlight_get_brightness(output->backlight);
1325         max_brightness = backlight_get_max_brightness(output->backlight);
1326
1327         /* convert it on a scale of 0 to 255 */
1328         norm = (brightness * 255)/(max_brightness);
1329
1330         return (uint32_t) norm;
1331 }
1332
1333 /* values accepted are between 0-255 range */
1334 static void
1335 drm_set_backlight(struct weston_output *output_base, uint32_t value)
1336 {
1337         struct drm_output *output = (struct drm_output *) output_base;
1338         long max_brightness, new_brightness;
1339
1340         if (!output->backlight)
1341                 return;
1342
1343         if (value > 255)
1344                 return;
1345
1346         max_brightness = backlight_get_max_brightness(output->backlight);
1347
1348         /* get denormalized value */
1349         new_brightness = (value * max_brightness) / 255;
1350
1351         backlight_set_brightness(output->backlight, new_brightness);
1352 }
1353
1354 static drmModePropertyPtr
1355 drm_get_prop(int fd, drmModeConnectorPtr connector, const char *name)
1356 {
1357         drmModePropertyPtr props;
1358         int i;
1359
1360         for (i = 0; i < connector->count_props; i++) {
1361                 props = drmModeGetProperty(fd, connector->props[i]);
1362                 if (!props)
1363                         continue;
1364
1365                 if (!strcmp(props->name, name))
1366                         return props;
1367
1368                 drmModeFreeProperty(props);
1369         }
1370
1371         return NULL;
1372 }
1373
1374 static void
1375 drm_set_dpms(struct weston_output *output_base, enum dpms_enum level)
1376 {
1377         struct drm_output *output = (struct drm_output *) output_base;
1378         struct weston_compositor *ec = output_base->compositor;
1379         struct drm_compositor *c = (struct drm_compositor *) ec;
1380
1381         if (!output->dpms_prop)
1382                 return;
1383
1384         drmModeConnectorSetProperty(c->drm.fd, output->connector_id,
1385                                     output->dpms_prop->prop_id, level);
1386 }
1387
1388 static const char *connector_type_names[] = {
1389         "None",
1390         "VGA",
1391         "DVI",
1392         "DVI",
1393         "DVI",
1394         "Composite",
1395         "TV",
1396         "LVDS",
1397         "CTV",
1398         "DIN",
1399         "DP",
1400         "HDMI",
1401         "HDMI",
1402         "TV",
1403         "eDP",
1404 };
1405
1406 static int
1407 find_crtc_for_connector(struct drm_compositor *ec,
1408                         drmModeRes *resources, drmModeConnector *connector)
1409 {
1410         drmModeEncoder *encoder;
1411         uint32_t possible_crtcs;
1412         int i, j;
1413
1414         for (j = 0; j < connector->count_encoders; j++) {
1415                 encoder = drmModeGetEncoder(ec->drm.fd, connector->encoders[j]);
1416                 if (encoder == NULL) {
1417                         weston_log("Failed to get encoder.\n");
1418                         return -1;
1419                 }
1420                 possible_crtcs = encoder->possible_crtcs;
1421                 drmModeFreeEncoder(encoder);
1422
1423                 for (i = 0; i < resources->count_crtcs; i++) {
1424                         if (possible_crtcs & (1 << i) &&
1425                             !(ec->crtc_allocator & (1 << resources->crtcs[i])))
1426                                 return i;
1427                 }
1428         }
1429
1430         return -1;
1431 }
1432
1433 /* Init output state that depends on gl or gbm */
1434 static int
1435 drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec)
1436 {
1437         int i, flags;
1438
1439         output->surface = gbm_surface_create(ec->gbm,
1440                                              output->base.current->width,
1441                                              output->base.current->height,
1442                                              GBM_FORMAT_XRGB8888,
1443                                              GBM_BO_USE_SCANOUT |
1444                                              GBM_BO_USE_RENDERING);
1445         if (!output->surface) {
1446                 weston_log("failed to create gbm surface\n");
1447                 return -1;
1448         }
1449
1450         if (gl_renderer_output_create(&output->base, output->surface) < 0) {
1451                 weston_log("failed to create gl renderer output state\n");
1452                 gbm_surface_destroy(output->surface);
1453                 return -1;
1454         }
1455
1456         flags = GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE;
1457
1458         for (i = 0; i < 2; i++) {
1459                 if (output->cursor_bo[i])
1460                         continue;
1461
1462                 output->cursor_bo[i] =
1463                         gbm_bo_create(ec->gbm, 64, 64, GBM_FORMAT_ARGB8888,
1464                                       flags);
1465         }
1466
1467         if (output->cursor_bo[0] == NULL || output->cursor_bo[1] == NULL) {
1468                 weston_log("cursor buffers unavailable, using gl cursors\n");
1469                 ec->cursors_are_broken = 1;
1470         }
1471
1472         return 0;
1473 }
1474
1475 static int
1476 drm_output_init_pixman(struct drm_output *output, struct drm_compositor *c)
1477 {
1478         int w = output->base.current->width;
1479         int h = output->base.current->height;
1480         unsigned int i;
1481
1482         /* FIXME error checking */
1483
1484         for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
1485                 output->dumb[i] = drm_fb_create_dumb(c, w, h);
1486                 if (!output->dumb[i])
1487                         goto err;
1488
1489                 output->image[i] =
1490                         pixman_image_create_bits(PIXMAN_x8r8g8b8, w, h,
1491                                                  output->dumb[i]->map,
1492                                                  output->dumb[i]->stride);
1493                 if (!output->image[i])
1494                         goto err;
1495         }
1496
1497         if (pixman_renderer_output_create(&output->base) < 0)
1498                 goto err;
1499
1500         pixman_region32_init_rect(&output->previous_damage,
1501                                   output->base.x, output->base.y, output->base.width, output->base.height);
1502
1503         return 0;
1504
1505 err:
1506         for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
1507                 if (output->dumb[i])
1508                         drm_fb_destroy_dumb(output->dumb[i]);
1509                 if (output->image[i])
1510                         pixman_image_unref(output->image[i]);
1511
1512                 output->dumb[i] = NULL;
1513                 output->image[i] = NULL;
1514         }
1515
1516         return -1;
1517 }
1518
1519 static void
1520 drm_output_fini_pixman(struct drm_output *output)
1521 {
1522         unsigned int i;
1523
1524         pixman_renderer_output_destroy(&output->base);
1525         pixman_region32_fini(&output->previous_damage);
1526
1527         for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
1528                 drm_fb_destroy_dumb(output->dumb[i]);
1529                 pixman_image_unref(output->image[i]);
1530                 output->dumb[i] = NULL;
1531                 output->image[i] = NULL;
1532         }
1533 }
1534
1535 static void
1536 edid_parse_string(const uint8_t *data, char text[])
1537 {
1538         int i;
1539         int replaced = 0;
1540
1541         /* this is always 12 bytes, but we can't guarantee it's null
1542          * terminated or not junk. */
1543         strncpy(text, (const char *) data, 12);
1544
1545         /* remove insane chars */
1546         for (i = 0; text[i] != '\0'; i++) {
1547                 if (text[i] == '\n' ||
1548                     text[i] == '\r') {
1549                         text[i] = '\0';
1550                         break;
1551                 }
1552         }
1553
1554         /* ensure string is printable */
1555         for (i = 0; text[i] != '\0'; i++) {
1556                 if (!isprint(text[i])) {
1557                         text[i] = '-';
1558                         replaced++;
1559                 }
1560         }
1561
1562         /* if the string is random junk, ignore the string */
1563         if (replaced > 4)
1564                 text[0] = '\0';
1565 }
1566
1567 #define EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING        0xfe
1568 #define EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME            0xfc
1569 #define EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER   0xff
1570 #define EDID_OFFSET_DATA_BLOCKS                         0x36
1571 #define EDID_OFFSET_LAST_BLOCK                          0x6c
1572 #define EDID_OFFSET_PNPID                               0x08
1573 #define EDID_OFFSET_SERIAL                              0x0c
1574
1575 static int
1576 edid_parse(struct drm_edid *edid, const uint8_t *data, size_t length)
1577 {
1578         int i;
1579         uint32_t serial_number;
1580
1581         /* check header */
1582         if (length < 128)
1583                 return -1;
1584         if (data[0] != 0x00 || data[1] != 0xff)
1585                 return -1;
1586
1587         /* decode the PNP ID from three 5 bit words packed into 2 bytes
1588          * /--08--\/--09--\
1589          * 7654321076543210
1590          * |\---/\---/\---/
1591          * R  C1   C2   C3 */
1592         edid->pnp_id[0] = 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x7c) / 4) - 1;
1593         edid->pnp_id[1] = 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x3) * 8) + ((data[EDID_OFFSET_PNPID + 1] & 0xe0) / 32) - 1;
1594         edid->pnp_id[2] = 'A' + (data[EDID_OFFSET_PNPID + 1] & 0x1f) - 1;
1595         edid->pnp_id[3] = '\0';
1596
1597         /* maybe there isn't a ASCII serial number descriptor, so use this instead */
1598         serial_number = (uint32_t) data[EDID_OFFSET_SERIAL + 0];
1599         serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 1] * 0x100;
1600         serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 2] * 0x10000;
1601         serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 3] * 0x1000000;
1602         if (serial_number > 0)
1603                 sprintf(edid->serial_number, "%lu", (unsigned long) serial_number);
1604
1605         /* parse EDID data */
1606         for (i = EDID_OFFSET_DATA_BLOCKS;
1607              i <= EDID_OFFSET_LAST_BLOCK;
1608              i += 18) {
1609                 /* ignore pixel clock data */
1610                 if (data[i] != 0)
1611                         continue;
1612                 if (data[i+2] != 0)
1613                         continue;
1614
1615                 /* any useful blocks? */
1616                 if (data[i+3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME) {
1617                         edid_parse_string(&data[i+5],
1618                                           edid->monitor_name);
1619                 } else if (data[i+3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER) {
1620                         edid_parse_string(&data[i+5],
1621                                           edid->serial_number);
1622                 } else if (data[i+3] == EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING) {
1623                         edid_parse_string(&data[i+5],
1624                                           edid->eisa_id);
1625                 }
1626         }
1627         return 0;
1628 }
1629
1630 static void
1631 find_and_parse_output_edid(struct drm_compositor *ec,
1632                            struct drm_output *output,
1633                            drmModeConnector *connector)
1634 {
1635         drmModePropertyBlobPtr edid_blob = NULL;
1636         drmModePropertyPtr property;
1637         int i;
1638         int rc;
1639
1640         for (i = 0; i < connector->count_props && !edid_blob; i++) {
1641                 property = drmModeGetProperty(ec->drm.fd, connector->props[i]);
1642                 if (!property)
1643                         continue;
1644                 if ((property->flags & DRM_MODE_PROP_BLOB) &&
1645                     !strcmp(property->name, "EDID")) {
1646                         edid_blob = drmModeGetPropertyBlob(ec->drm.fd,
1647                                                            connector->prop_values[i]);
1648                 }
1649                 drmModeFreeProperty(property);
1650         }
1651         if (!edid_blob)
1652                 return;
1653
1654         rc = edid_parse(&output->edid,
1655                         edid_blob->data,
1656                         edid_blob->length);
1657         if (!rc) {
1658                 weston_log("EDID data '%s', '%s', '%s'\n",
1659                            output->edid.pnp_id,
1660                            output->edid.monitor_name,
1661                            output->edid.serial_number);
1662                 if (output->edid.pnp_id[0] != '\0')
1663                         output->base.make = output->edid.pnp_id;
1664                 if (output->edid.monitor_name[0] != '\0')
1665                         output->base.model = output->edid.monitor_name;
1666                 if (output->edid.serial_number[0] != '\0')
1667                         output->base.serial_number = output->edid.serial_number;
1668         }
1669         drmModeFreePropertyBlob(edid_blob);
1670 }
1671
1672
1673
1674 static int
1675 parse_modeline(const char *s, drmModeModeInfo *mode)
1676 {
1677         char hsync[16];
1678         char vsync[16];
1679         float fclock;
1680
1681         mode->type = DRM_MODE_TYPE_USERDEF;
1682         mode->hskew = 0;
1683         mode->vscan = 0;
1684         mode->vrefresh = 0;
1685         mode->flags = 0;
1686
1687         if (sscanf(s, "%f %hd %hd %hd %hd %hd %hd %hd %hd %15s %15s",
1688                    &fclock,
1689                    &mode->hdisplay,
1690                    &mode->hsync_start,
1691                    &mode->hsync_end,
1692                    &mode->htotal,
1693                    &mode->vdisplay,
1694                    &mode->vsync_start,
1695                    &mode->vsync_end,
1696                    &mode->vtotal, hsync, vsync) != 11)
1697                 return -1;
1698
1699         mode->clock = fclock * 1000;
1700         if (strcmp(hsync, "+hsync") == 0)
1701                 mode->flags |= DRM_MODE_FLAG_PHSYNC;
1702         else if (strcmp(hsync, "-hsync") == 0)
1703                 mode->flags |= DRM_MODE_FLAG_NHSYNC;
1704         else
1705                 return -1;
1706
1707         if (strcmp(vsync, "+vsync") == 0)
1708                 mode->flags |= DRM_MODE_FLAG_PVSYNC;
1709         else if (strcmp(vsync, "-vsync") == 0)
1710                 mode->flags |= DRM_MODE_FLAG_NVSYNC;
1711         else
1712                 return -1;
1713
1714         return 0;
1715 }
1716
1717 static uint32_t
1718 parse_transform(const char *transform, const char *output_name)
1719 {
1720         static const struct { const char *name; uint32_t token; } names[] = {
1721                 { "normal",     WL_OUTPUT_TRANSFORM_NORMAL },
1722                 { "90",         WL_OUTPUT_TRANSFORM_90 },
1723                 { "180",        WL_OUTPUT_TRANSFORM_180 },
1724                 { "270",        WL_OUTPUT_TRANSFORM_270 },
1725                 { "flipped",    WL_OUTPUT_TRANSFORM_FLIPPED },
1726                 { "flipped-90", WL_OUTPUT_TRANSFORM_FLIPPED_90 },
1727                 { "flipped-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 },
1728                 { "flipped-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 },
1729         };
1730         unsigned int i;
1731
1732         for (i = 0; i < ARRAY_LENGTH(names); i++)
1733                 if (strcmp(names[i].name, transform) == 0)
1734                         return names[i].token;
1735
1736         weston_log("Invalid transform \"%s\" for output %s\n",
1737                    transform, output_name);
1738
1739         return WL_OUTPUT_TRANSFORM_NORMAL;
1740 }
1741
1742 static void
1743 setup_output_seat_constraint(struct drm_compositor *ec,
1744                              struct weston_output *output,
1745                              const char *s)
1746 {
1747         if (strcmp(s, "") != 0) {
1748                 struct udev_seat *seat;
1749
1750                 seat = udev_seat_get_named(&ec->base, s);
1751                 if (seat)
1752                         seat->base.output = output;
1753
1754                 if (seat && seat->base.pointer)
1755                         weston_pointer_clamp(seat->base.pointer,
1756                                              &seat->base.pointer->x,
1757                                              &seat->base.pointer->y);
1758         }
1759 }
1760
1761 static int
1762 create_output_for_connector(struct drm_compositor *ec,
1763                             drmModeRes *resources,
1764                             drmModeConnector *connector,
1765                             int x, int y, struct udev_device *drm_device)
1766 {
1767         struct drm_output *output;
1768         struct drm_mode *drm_mode, *next, *preferred, *current, *configured;
1769         struct weston_mode *m;
1770         struct weston_config_section *section;
1771         drmModeEncoder *encoder;
1772         drmModeModeInfo crtc_mode, modeline;
1773         drmModeCrtc *crtc;
1774         int i, width, height, scale;
1775         char name[32], *s;
1776         const char *type_name;
1777         enum output_config config;
1778         uint32_t transform;
1779
1780         i = find_crtc_for_connector(ec, resources, connector);
1781         if (i < 0) {
1782                 weston_log("No usable crtc/encoder pair for connector.\n");
1783                 return -1;
1784         }
1785
1786         output = zalloc(sizeof *output);
1787         if (output == NULL)
1788                 return -1;
1789
1790         output->base.subpixel = drm_subpixel_to_wayland(connector->subpixel);
1791         output->base.make = "unknown";
1792         output->base.model = "unknown";
1793         output->base.serial_number = "unknown";
1794         wl_list_init(&output->base.mode_list);
1795
1796         if (connector->connector_type < ARRAY_LENGTH(connector_type_names))
1797                 type_name = connector_type_names[connector->connector_type];
1798         else
1799                 type_name = "UNKNOWN";
1800         snprintf(name, 32, "%s%d", type_name, connector->connector_type_id);
1801         output->base.name = strdup(name);
1802
1803         section = weston_config_get_section(ec->base.config, "output", "name",
1804                                             output->base.name);
1805         weston_config_section_get_string(section, "mode", &s, "preferred");
1806         if (strcmp(s, "off") == 0)
1807                 config = OUTPUT_CONFIG_OFF;
1808         else if (strcmp(s, "preferred") == 0)
1809                 config = OUTPUT_CONFIG_PREFERRED;
1810         else if (strcmp(s, "current") == 0)
1811                 config = OUTPUT_CONFIG_CURRENT;
1812         else if (sscanf(s, "%dx%d", &width, &height) == 2)
1813                 config = OUTPUT_CONFIG_MODE;
1814         else if (parse_modeline(s, &modeline) == 0)
1815                 config = OUTPUT_CONFIG_MODELINE;
1816         else {
1817                 weston_log("Invalid mode \"%s\" for output %s\n",
1818                            s, output->base.name);
1819                 config = OUTPUT_CONFIG_PREFERRED;
1820         }
1821         free(s);
1822
1823         weston_config_section_get_int(section, "scale", &scale, 1);
1824         weston_config_section_get_string(section, "transform", &s, "normal");
1825         transform = parse_transform(s, output->base.name);
1826         free(s);
1827
1828         weston_config_section_get_string(section, "seat", &s, "");
1829         setup_output_seat_constraint(ec, &output->base, s);
1830         free(s);
1831
1832         output->crtc_id = resources->crtcs[i];
1833         output->pipe = i;
1834         ec->crtc_allocator |= (1 << output->crtc_id);
1835         output->connector_id = connector->connector_id;
1836         ec->connector_allocator |= (1 << output->connector_id);
1837
1838         output->original_crtc = drmModeGetCrtc(ec->drm.fd, output->crtc_id);
1839         output->dpms_prop = drm_get_prop(ec->drm.fd, connector, "DPMS");
1840
1841         /* Get the current mode on the crtc that's currently driving
1842          * this connector. */
1843         encoder = drmModeGetEncoder(ec->drm.fd, connector->encoder_id);
1844         memset(&crtc_mode, 0, sizeof crtc_mode);
1845         if (encoder != NULL) {
1846                 crtc = drmModeGetCrtc(ec->drm.fd, encoder->crtc_id);
1847                 drmModeFreeEncoder(encoder);
1848                 if (crtc == NULL)
1849                         goto err_free;
1850                 if (crtc->mode_valid)
1851                         crtc_mode = crtc->mode;
1852                 drmModeFreeCrtc(crtc);
1853         }
1854
1855         for (i = 0; i < connector->count_modes; i++) {
1856                 drm_mode = drm_output_add_mode(output, &connector->modes[i]);
1857                 if (!drm_mode)
1858                         goto err_free;
1859         }
1860
1861         if (config == OUTPUT_CONFIG_OFF) {
1862                 weston_log("Disabling output %s\n", output->base.name);
1863                 drmModeSetCrtc(ec->drm.fd, output->crtc_id,
1864                                0, 0, 0, 0, 0, NULL);
1865                 goto err_free;
1866         }
1867
1868         preferred = NULL;
1869         current = NULL;
1870         configured = NULL;
1871
1872         wl_list_for_each_reverse(drm_mode, &output->base.mode_list, base.link) {
1873                 if (config == OUTPUT_CONFIG_MODE &&
1874                     width == drm_mode->base.width &&
1875                     height == drm_mode->base.height)
1876                         configured = drm_mode;
1877                 if (!memcmp(&crtc_mode, &drm_mode->mode_info, sizeof crtc_mode))
1878                         current = drm_mode;
1879                 if (drm_mode->base.flags & WL_OUTPUT_MODE_PREFERRED)
1880                         preferred = drm_mode;
1881         }
1882
1883         if (config == OUTPUT_CONFIG_MODELINE) {
1884                 configured = drm_output_add_mode(output, &modeline);
1885                 if (!configured)
1886                         goto err_free;
1887         }
1888
1889         if (current == NULL && crtc_mode.clock != 0) {
1890                 current = drm_output_add_mode(output, &crtc_mode);
1891                 if (!current)
1892                         goto err_free;
1893         }
1894
1895         if (config == OUTPUT_CONFIG_CURRENT)
1896                 configured = current;
1897
1898         if (option_current_mode && current)
1899                 output->base.current = &current->base;
1900         else if (configured)
1901                 output->base.current = &configured->base;
1902         else if (preferred)
1903                 output->base.current = &preferred->base;
1904         else if (current)
1905                 output->base.current = &current->base;
1906
1907         if (output->base.current == NULL) {
1908                 weston_log("no available modes for %s\n", output->base.name);
1909                 goto err_free;
1910         }
1911
1912         output->base.current->flags |= WL_OUTPUT_MODE_CURRENT;
1913
1914         weston_output_init(&output->base, &ec->base, x, y,
1915                            connector->mmWidth, connector->mmHeight,
1916                            transform, scale);
1917
1918         if (ec->use_pixman) {
1919                 if (drm_output_init_pixman(output, ec) < 0) {
1920                         weston_log("Failed to init output pixman state\n");
1921                         goto err_output;
1922                 }
1923         } else if (drm_output_init_egl(output, ec) < 0) {
1924                 weston_log("Failed to init output gl state\n");
1925                 goto err_output;
1926         }
1927
1928         output->backlight = backlight_init(drm_device,
1929                                            connector->connector_type);
1930         if (output->backlight) {
1931                 weston_log("Initialized backlight, device %s\n",
1932                            output->backlight->path);
1933                 output->base.set_backlight = drm_set_backlight;
1934                 output->base.backlight_current = drm_get_backlight(output);
1935         } else {
1936                 weston_log("Failed to initialize backlight\n");
1937         }
1938
1939         wl_list_insert(ec->base.output_list.prev, &output->base.link);
1940
1941         find_and_parse_output_edid(ec, output, connector);
1942         if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
1943                 output->base.connection_internal = 1;
1944
1945         output->base.origin = output->base.current;
1946         output->base.start_repaint_loop = drm_output_start_repaint_loop;
1947         output->base.repaint = drm_output_repaint;
1948         output->base.destroy = drm_output_destroy;
1949         output->base.assign_planes = drm_assign_planes;
1950         output->base.set_dpms = drm_set_dpms;
1951         output->base.switch_mode = drm_output_switch_mode;
1952
1953         output->base.gamma_size = output->original_crtc->gamma_size;
1954         output->base.set_gamma = drm_output_set_gamma;
1955
1956         weston_plane_init(&output->cursor_plane, 0, 0);
1957         weston_plane_init(&output->fb_plane, 0, 0);
1958
1959         weston_compositor_stack_plane(&ec->base, &output->cursor_plane, NULL);
1960         weston_compositor_stack_plane(&ec->base, &output->fb_plane,
1961                                       &ec->base.primary_plane);
1962
1963         weston_log("Output %s, (connector %d, crtc %d)\n",
1964                    output->base.name, output->connector_id, output->crtc_id);
1965         wl_list_for_each(m, &output->base.mode_list, link)
1966                 weston_log_continue("  mode %dx%d@%.1f%s%s%s\n",
1967                                     m->width, m->height, m->refresh / 1000.0,
1968                                     m->flags & WL_OUTPUT_MODE_PREFERRED ?
1969                                     ", preferred" : "",
1970                                     m->flags & WL_OUTPUT_MODE_CURRENT ?
1971                                     ", current" : "",
1972                                     connector->count_modes == 0 ?
1973                                     ", built-in" : "");
1974
1975         return 0;
1976
1977 err_output:
1978         weston_output_destroy(&output->base);
1979 err_free:
1980         wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
1981                                                         base.link) {
1982                 wl_list_remove(&drm_mode->base.link);
1983                 free(drm_mode);
1984         }
1985
1986         drmModeFreeCrtc(output->original_crtc);
1987         ec->crtc_allocator &= ~(1 << output->crtc_id);
1988         ec->connector_allocator &= ~(1 << output->connector_id);
1989         free(output);
1990
1991         return -1;
1992 }
1993
1994 static void
1995 create_sprites(struct drm_compositor *ec)
1996 {
1997         struct drm_sprite *sprite;
1998         drmModePlaneRes *plane_res;
1999         drmModePlane *plane;
2000         uint32_t i;
2001
2002         plane_res = drmModeGetPlaneResources(ec->drm.fd);
2003         if (!plane_res) {
2004                 weston_log("failed to get plane resources: %s\n",
2005                         strerror(errno));
2006                 return;
2007         }
2008
2009         for (i = 0; i < plane_res->count_planes; i++) {
2010                 plane = drmModeGetPlane(ec->drm.fd, plane_res->planes[i]);
2011                 if (!plane)
2012                         continue;
2013
2014                 sprite = zalloc(sizeof(*sprite) + ((sizeof(uint32_t)) *
2015                                                    plane->count_formats));
2016                 if (!sprite) {
2017                         weston_log("%s: out of memory\n",
2018                                 __func__);
2019                         free(plane);
2020                         continue;
2021                 }
2022
2023                 sprite->possible_crtcs = plane->possible_crtcs;
2024                 sprite->plane_id = plane->plane_id;
2025                 sprite->current = NULL;
2026                 sprite->next = NULL;
2027                 sprite->compositor = ec;
2028                 sprite->count_formats = plane->count_formats;
2029                 memcpy(sprite->formats, plane->formats,
2030                        plane->count_formats * sizeof(plane->formats[0]));
2031                 drmModeFreePlane(plane);
2032                 weston_plane_init(&sprite->plane, 0, 0);
2033                 weston_compositor_stack_plane(&ec->base, &sprite->plane,
2034                                               &ec->base.primary_plane);
2035
2036                 wl_list_insert(&ec->sprite_list, &sprite->link);
2037         }
2038
2039         drmModeFreePlaneResources(plane_res);
2040 }
2041
2042 static void
2043 destroy_sprites(struct drm_compositor *compositor)
2044 {
2045         struct drm_sprite *sprite, *next;
2046         struct drm_output *output;
2047
2048         output = container_of(compositor->base.output_list.next,
2049                               struct drm_output, base.link);
2050
2051         wl_list_for_each_safe(sprite, next, &compositor->sprite_list, link) {
2052                 drmModeSetPlane(compositor->drm.fd,
2053                                 sprite->plane_id,
2054                                 output->crtc_id, 0, 0,
2055                                 0, 0, 0, 0, 0, 0, 0, 0);
2056                 drm_output_release_fb(output, sprite->current);
2057                 drm_output_release_fb(output, sprite->next);
2058                 weston_plane_release(&sprite->plane);
2059                 free(sprite);
2060         }
2061 }
2062
2063 static int
2064 create_outputs(struct drm_compositor *ec, uint32_t option_connector,
2065                struct udev_device *drm_device)
2066 {
2067         drmModeConnector *connector;
2068         drmModeRes *resources;
2069         int i;
2070         int x = 0, y = 0;
2071
2072         resources = drmModeGetResources(ec->drm.fd);
2073         if (!resources) {
2074                 weston_log("drmModeGetResources failed\n");
2075                 return -1;
2076         }
2077
2078         ec->crtcs = calloc(resources->count_crtcs, sizeof(uint32_t));
2079         if (!ec->crtcs) {
2080                 drmModeFreeResources(resources);
2081                 return -1;
2082         }
2083
2084         ec->min_width  = resources->min_width;
2085         ec->max_width  = resources->max_width;
2086         ec->min_height = resources->min_height;
2087         ec->max_height = resources->max_height;
2088
2089         ec->num_crtcs = resources->count_crtcs;
2090         memcpy(ec->crtcs, resources->crtcs, sizeof(uint32_t) * ec->num_crtcs);
2091
2092         for (i = 0; i < resources->count_connectors; i++) {
2093                 connector = drmModeGetConnector(ec->drm.fd,
2094                                                 resources->connectors[i]);
2095                 if (connector == NULL)
2096                         continue;
2097
2098                 if (connector->connection == DRM_MODE_CONNECTED &&
2099                     (option_connector == 0 ||
2100                      connector->connector_id == option_connector)) {
2101                         if (create_output_for_connector(ec, resources,
2102                                                         connector, x, y,
2103                                                         drm_device) < 0) {
2104                                 drmModeFreeConnector(connector);
2105                                 continue;
2106                         }
2107
2108                         x += container_of(ec->base.output_list.prev,
2109                                           struct weston_output,
2110                                           link)->width;
2111                 }
2112
2113                 drmModeFreeConnector(connector);
2114         }
2115
2116         if (wl_list_empty(&ec->base.output_list)) {
2117                 weston_log("No currently active connector found.\n");
2118                 drmModeFreeResources(resources);
2119                 return -1;
2120         }
2121
2122         drmModeFreeResources(resources);
2123
2124         return 0;
2125 }
2126
2127 static void
2128 update_outputs(struct drm_compositor *ec, struct udev_device *drm_device)
2129 {
2130         drmModeConnector *connector;
2131         drmModeRes *resources;
2132         struct drm_output *output, *next;
2133         int x = 0, y = 0;
2134         int x_offset = 0, y_offset = 0;
2135         uint32_t connected = 0, disconnects = 0;
2136         int i;
2137
2138         resources = drmModeGetResources(ec->drm.fd);
2139         if (!resources) {
2140                 weston_log("drmModeGetResources failed\n");
2141                 return;
2142         }
2143
2144         /* collect new connects */
2145         for (i = 0; i < resources->count_connectors; i++) {
2146                 int connector_id = resources->connectors[i];
2147
2148                 connector = drmModeGetConnector(ec->drm.fd, connector_id);
2149                 if (connector == NULL)
2150                         continue;
2151
2152                 if (connector->connection != DRM_MODE_CONNECTED) {
2153                         drmModeFreeConnector(connector);
2154                         continue;
2155                 }
2156
2157                 connected |= (1 << connector_id);
2158
2159                 if (!(ec->connector_allocator & (1 << connector_id))) {
2160                         struct weston_output *last =
2161                                 container_of(ec->base.output_list.prev,
2162                                              struct weston_output, link);
2163
2164                         /* XXX: not yet needed, we die with 0 outputs */
2165                         if (!wl_list_empty(&ec->base.output_list))
2166                                 x = last->x + last->width;
2167                         else
2168                                 x = 0;
2169                         y = 0;
2170                         create_output_for_connector(ec, resources,
2171                                                     connector, x, y,
2172                                                     drm_device);
2173                         weston_log("connector %d connected\n", connector_id);
2174
2175                 }
2176                 drmModeFreeConnector(connector);
2177         }
2178         drmModeFreeResources(resources);
2179
2180         disconnects = ec->connector_allocator & ~connected;
2181         if (disconnects) {
2182                 wl_list_for_each_safe(output, next, &ec->base.output_list,
2183                                       base.link) {
2184                         if (x_offset != 0 || y_offset != 0) {
2185                                 weston_output_move(&output->base,
2186                                                  output->base.x - x_offset,
2187                                                  output->base.y - y_offset);
2188                         }
2189
2190                         if (disconnects & (1 << output->connector_id)) {
2191                                 disconnects &= ~(1 << output->connector_id);
2192                                 weston_log("connector %d disconnected\n",
2193                                        output->connector_id);
2194                                 x_offset += output->base.width;
2195                                 drm_output_destroy(&output->base);
2196                         }
2197                 }
2198         }
2199
2200         /* FIXME: handle zero outputs, without terminating */   
2201         if (ec->connector_allocator == 0)
2202                 wl_display_terminate(ec->base.wl_display);
2203 }
2204
2205 static int
2206 udev_event_is_hotplug(struct drm_compositor *ec, struct udev_device *device)
2207 {
2208         const char *sysnum;
2209         const char *val;
2210
2211         sysnum = udev_device_get_sysnum(device);
2212         if (!sysnum || atoi(sysnum) != ec->drm.id)
2213                 return 0;
2214
2215         val = udev_device_get_property_value(device, "HOTPLUG");
2216         if (!val)
2217                 return 0;
2218
2219         return strcmp(val, "1") == 0;
2220 }
2221
2222 static int
2223 udev_drm_event(int fd, uint32_t mask, void *data)
2224 {
2225         struct drm_compositor *ec = data;
2226         struct udev_device *event;
2227
2228         event = udev_monitor_receive_device(ec->udev_monitor);
2229
2230         if (udev_event_is_hotplug(ec, event))
2231                 update_outputs(ec, event);
2232
2233         udev_device_unref(event);
2234
2235         return 1;
2236 }
2237
2238 static void
2239 drm_restore(struct weston_compositor *ec)
2240 {
2241         struct drm_compositor *d = (struct drm_compositor *) ec;
2242
2243         if (weston_launcher_drm_set_master(&d->base, d->drm.fd, 0) < 0)
2244                 weston_log("failed to drop master: %m\n");
2245         tty_reset(d->tty);
2246 }
2247
2248 static void
2249 drm_destroy(struct weston_compositor *ec)
2250 {
2251         struct drm_compositor *d = (struct drm_compositor *) ec;
2252
2253         udev_input_destroy(&d->input);
2254
2255         wl_event_source_remove(d->udev_drm_source);
2256         wl_event_source_remove(d->drm_source);
2257
2258         destroy_sprites(d);
2259
2260         weston_compositor_shutdown(ec);
2261
2262         ec->renderer->destroy(ec);
2263
2264         if (d->gbm)
2265                 gbm_device_destroy(d->gbm);
2266
2267         if (weston_launcher_drm_set_master(&d->base, d->drm.fd, 0) < 0)
2268                 weston_log("failed to drop master: %m\n");
2269         tty_destroy(d->tty);
2270
2271         close(d->drm.fd);
2272
2273         free(d);
2274 }
2275
2276 static void
2277 drm_compositor_set_modes(struct drm_compositor *compositor)
2278 {
2279         struct drm_output *output;
2280         struct drm_mode *drm_mode;
2281         int ret;
2282
2283         wl_list_for_each(output, &compositor->base.output_list, base.link) {
2284                 if (!output->current) {
2285                         /* If something that would cause the output to
2286                          * switch mode happened while in another vt, we
2287                          * might not have a current drm_fb. In that case,
2288                          * schedule a repaint and let drm_output_repaint
2289                          * handle setting the mode. */
2290                         weston_output_schedule_repaint(&output->base);
2291                         continue;
2292                 }
2293
2294                 drm_mode = (struct drm_mode *) output->base.current;
2295                 ret = drmModeSetCrtc(compositor->drm.fd, output->crtc_id,
2296                                      output->current->fb_id, 0, 0,
2297                                      &output->connector_id, 1,
2298                                      &drm_mode->mode_info);
2299                 if (ret < 0) {
2300                         weston_log(
2301                                 "failed to set mode %dx%d for output at %d,%d: %m\n",
2302                                 drm_mode->base.width, drm_mode->base.height, 
2303                                 output->base.x, output->base.y);
2304                 }
2305         }
2306 }
2307
2308 static void
2309 vt_func(struct weston_compositor *compositor, int event)
2310 {
2311         struct drm_compositor *ec = (struct drm_compositor *) compositor;
2312         struct drm_sprite *sprite;
2313         struct drm_output *output;
2314
2315         switch (event) {
2316         case TTY_ENTER_VT:
2317                 weston_log("entering VT\n");
2318                 compositor->focus = 1;
2319                 if (weston_launcher_drm_set_master(&ec->base, ec->drm.fd, 1)) {
2320                         weston_log("failed to set master: %m\n");
2321                         wl_display_terminate(compositor->wl_display);
2322                 }
2323                 compositor->state = ec->prev_state;
2324                 drm_compositor_set_modes(ec);
2325                 weston_compositor_damage_all(compositor);
2326                 udev_input_enable(&ec->input, ec->udev);
2327                 break;
2328         case TTY_LEAVE_VT:
2329                 weston_log("leaving VT\n");
2330                 udev_input_disable(&ec->input);
2331
2332                 compositor->focus = 0;
2333                 ec->prev_state = compositor->state;
2334                 weston_compositor_offscreen(compositor);
2335
2336                 /* If we have a repaint scheduled (either from a
2337                  * pending pageflip or the idle handler), make sure we
2338                  * cancel that so we don't try to pageflip when we're
2339                  * vt switched away.  The OFFSCREEN state will prevent
2340                  * further attemps at repainting.  When we switch
2341                  * back, we schedule a repaint, which will process
2342                  * pending frame callbacks. */
2343
2344                 wl_list_for_each(output, &ec->base.output_list, base.link) {
2345                         output->base.repaint_needed = 0;
2346                         drmModeSetCursor(ec->drm.fd, output->crtc_id, 0, 0, 0);
2347                 }
2348
2349                 output = container_of(ec->base.output_list.next,
2350                                       struct drm_output, base.link);
2351
2352                 wl_list_for_each(sprite, &ec->sprite_list, link)
2353                         drmModeSetPlane(ec->drm.fd,
2354                                         sprite->plane_id,
2355                                         output->crtc_id, 0, 0,
2356                                         0, 0, 0, 0, 0, 0, 0, 0);
2357
2358                 if (weston_launcher_drm_set_master(&ec->base, ec->drm.fd, 0) < 0)
2359                         weston_log("failed to drop master: %m\n");
2360
2361                 break;
2362         };
2363 }
2364
2365 static void
2366 switch_vt_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *data)
2367 {
2368         struct drm_compositor *ec = data;
2369
2370         tty_activate_vt(ec->tty, key - KEY_F1 + 1);
2371 }
2372
2373 /*
2374  * Find primary GPU
2375  * Some systems may have multiple DRM devices attached to a single seat. This
2376  * function loops over all devices and tries to find a PCI device with the
2377  * boot_vga sysfs attribute set to 1.
2378  * If no such device is found, the first DRM device reported by udev is used.
2379  */
2380 static struct udev_device*
2381 find_primary_gpu(struct drm_compositor *ec, const char *seat)
2382 {
2383         struct udev_enumerate *e;
2384         struct udev_list_entry *entry;
2385         const char *path, *device_seat, *id;
2386         struct udev_device *device, *drm_device, *pci;
2387
2388         e = udev_enumerate_new(ec->udev);
2389         udev_enumerate_add_match_subsystem(e, "drm");
2390         udev_enumerate_add_match_sysname(e, "card[0-9]*");
2391
2392         udev_enumerate_scan_devices(e);
2393         drm_device = NULL;
2394         udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
2395                 path = udev_list_entry_get_name(entry);
2396                 device = udev_device_new_from_syspath(ec->udev, path);
2397                 if (!device)
2398                         continue;
2399                 device_seat = udev_device_get_property_value(device, "ID_SEAT");
2400                 if (!device_seat)
2401                         device_seat = default_seat;
2402                 if (strcmp(device_seat, seat)) {
2403                         udev_device_unref(device);
2404                         continue;
2405                 }
2406
2407                 pci = udev_device_get_parent_with_subsystem_devtype(device,
2408                                                                 "pci", NULL);
2409                 if (pci) {
2410                         id = udev_device_get_sysattr_value(pci, "boot_vga");
2411                         if (id && !strcmp(id, "1")) {
2412                                 if (drm_device)
2413                                         udev_device_unref(drm_device);
2414                                 drm_device = device;
2415                                 break;
2416                         }
2417                 }
2418
2419                 if (!drm_device)
2420                         drm_device = device;
2421                 else
2422                         udev_device_unref(device);
2423         }
2424
2425         udev_enumerate_unref(e);
2426         return drm_device;
2427 }
2428
2429 static void
2430 planes_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *data)
2431 {
2432         struct drm_compositor *c = data;
2433
2434         switch (key) {
2435         case KEY_C:
2436                 c->cursors_are_broken ^= 1;
2437                 break;
2438         case KEY_V:
2439                 c->sprites_are_broken ^= 1;
2440                 break;
2441         case KEY_O:
2442                 c->sprites_hidden ^= 1;
2443                 break;
2444         default:
2445                 break;
2446         }
2447 }
2448
2449 #ifdef BUILD_VAAPI_RECORDER
2450 static void
2451 recorder_frame_notify(struct wl_listener *listener, void *data)
2452 {
2453         struct drm_output *output;
2454         struct drm_compositor *c;
2455         int fd, ret;
2456
2457         output = container_of(listener, struct drm_output,
2458                               recorder_frame_listener);
2459         c = (struct drm_compositor *) output->base.compositor;
2460
2461         if (!output->recorder)
2462                 return;
2463
2464         ret = drmPrimeHandleToFD(c->drm.fd, output->current->handle,
2465                                  DRM_CLOEXEC, &fd);
2466         if (ret) {
2467                 weston_log("[libva recorder] "
2468                            "failed to create prime fd for front buffer\n");
2469                 return;
2470         }
2471
2472         vaapi_recorder_frame(output->recorder, fd, output->current->stride / 4);
2473
2474         close(fd);
2475 }
2476
2477 static void *
2478 create_recorder(struct drm_compositor *c, int width, int height,
2479                 const char *filename)
2480 {
2481         int fd;
2482         drm_magic_t magic;
2483
2484         fd = open(c->drm.filename, O_RDWR | O_CLOEXEC);
2485         if (fd < 0)
2486                 return NULL;
2487
2488         drmGetMagic(fd, &magic);
2489         drmAuthMagic(c->drm.fd, magic);
2490
2491         return vaapi_recorder_create(fd, width, height, filename);
2492 }
2493
2494 static void
2495 recorder_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
2496                  void *data)
2497 {
2498         struct drm_compositor *c = data;
2499         struct drm_output *output;
2500         int width, height;
2501
2502         output = container_of(c->base.output_list.next,
2503                               struct drm_output, base.link);
2504
2505         if (!output->recorder) {
2506                 width = output->base.current->width;
2507                 height = output->base.current->height;
2508
2509                 output->recorder =
2510                         create_recorder(c, width, height, "capture.h264");
2511                 if (!output->recorder) {
2512                         weston_log("failed to create vaapi recorder\n");
2513                         return;
2514                 }
2515
2516                 output->base.disable_planes++;
2517
2518                 output->recorder_frame_listener.notify = recorder_frame_notify;
2519                 wl_signal_add(&output->base.frame_signal,
2520                               &output->recorder_frame_listener);
2521
2522                 weston_output_schedule_repaint(&output->base);
2523
2524                 weston_log("[libva recorder] initialized\n");
2525         } else {
2526                 vaapi_recorder_destroy(output->recorder);
2527                 /* FIXME: close drm fd passed to recorder */
2528                 output->recorder = NULL;
2529
2530                 output->base.disable_planes--;
2531
2532                 wl_list_remove(&output->recorder_frame_listener.link);
2533                 weston_log("[libva recorder] done\n");
2534         }
2535 }
2536 #else
2537 static void
2538 recorder_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
2539                  void *data)
2540 {
2541         weston_log("Compiled without libva support\n");
2542 }
2543 #endif
2544
2545 static struct weston_compositor *
2546 drm_compositor_create(struct wl_display *display,
2547                       int connector, const char *seat_id, int tty, int pixman,
2548                       int *argc, char *argv[],
2549                       struct weston_config *config)
2550 {
2551         struct drm_compositor *ec;
2552         struct udev_device *drm_device;
2553         struct wl_event_loop *loop;
2554         const char *path;
2555         uint32_t key;
2556
2557         weston_log("initializing drm backend\n");
2558
2559         ec = zalloc(sizeof *ec);
2560         if (ec == NULL)
2561                 return NULL;
2562
2563         /* KMS support for sprites is not complete yet, so disable the
2564          * functionality for now. */
2565         ec->sprites_are_broken = 1;
2566
2567         ec->use_pixman = pixman;
2568
2569         if (weston_compositor_init(&ec->base, display, argc, argv,
2570                                    config) < 0) {
2571                 weston_log("%s failed\n", __func__);
2572                 goto err_base;
2573         }
2574
2575         /* Check if we run drm-backend using weston-launch */
2576         ec->base.launcher_sock =
2577                 weston_environment_get_fd("WESTON_LAUNCHER_SOCK");
2578         if (ec->base.launcher_sock == -1 && geteuid() != 0) {
2579                 weston_log("fatal: drm backend should be run "
2580                            "using weston-launch binary or as root\n");
2581                 goto err_compositor;
2582         }
2583
2584         ec->udev = udev_new();
2585         if (ec->udev == NULL) {
2586                 weston_log("failed to initialize udev context\n");
2587                 goto err_compositor;
2588         }
2589
2590         ec->base.wl_display = display;
2591         ec->tty = tty_create(&ec->base, vt_func, tty);
2592         if (!ec->tty) {
2593                 weston_log("failed to initialize tty\n");
2594                 goto err_udev;
2595         }
2596
2597         drm_device = find_primary_gpu(ec, seat_id);
2598         if (drm_device == NULL) {
2599                 weston_log("no drm device found\n");
2600                 goto err_tty;
2601         }
2602         path = udev_device_get_syspath(drm_device);
2603
2604         if (init_drm(ec, drm_device) < 0) {
2605                 weston_log("failed to initialize kms\n");
2606                 goto err_udev_dev;
2607         }
2608
2609         if (ec->use_pixman) {
2610                 if (init_pixman(ec) < 0) {
2611                         weston_log("failed to initialize pixman renderer\n");
2612                         goto err_udev_dev;
2613                 }
2614         } else {
2615                 if (init_egl(ec) < 0) {
2616                         weston_log("failed to initialize egl\n");
2617                         goto err_udev_dev;
2618                 }
2619         }
2620
2621         ec->base.destroy = drm_destroy;
2622         ec->base.restore = drm_restore;
2623
2624         ec->base.focus = 1;
2625
2626         ec->prev_state = WESTON_COMPOSITOR_ACTIVE;
2627
2628         for (key = KEY_F1; key < KEY_F9; key++)
2629                 weston_compositor_add_key_binding(&ec->base, key,
2630                                                   MODIFIER_CTRL | MODIFIER_ALT,
2631                                                   switch_vt_binding, ec);
2632
2633         wl_list_init(&ec->sprite_list);
2634         create_sprites(ec);
2635
2636         if (create_outputs(ec, connector, drm_device) < 0) {
2637                 weston_log("failed to create output for %s\n", path);
2638                 goto err_sprite;
2639         }
2640
2641         path = NULL;
2642
2643         if (udev_input_init(&ec->input, &ec->base, ec->udev, seat_id) < 0) {
2644                 weston_log("failed to create input devices\n");
2645                 goto err_sprite;
2646         }
2647
2648         loop = wl_display_get_event_loop(ec->base.wl_display);
2649         ec->drm_source =
2650                 wl_event_loop_add_fd(loop, ec->drm.fd,
2651                                      WL_EVENT_READABLE, on_drm_input, ec);
2652
2653         ec->udev_monitor = udev_monitor_new_from_netlink(ec->udev, "udev");
2654         if (ec->udev_monitor == NULL) {
2655                 weston_log("failed to intialize udev monitor\n");
2656                 goto err_drm_source;
2657         }
2658         udev_monitor_filter_add_match_subsystem_devtype(ec->udev_monitor,
2659                                                         "drm", NULL);
2660         ec->udev_drm_source =
2661                 wl_event_loop_add_fd(loop,
2662                                      udev_monitor_get_fd(ec->udev_monitor),
2663                                      WL_EVENT_READABLE, udev_drm_event, ec);
2664
2665         if (udev_monitor_enable_receiving(ec->udev_monitor) < 0) {
2666                 weston_log("failed to enable udev-monitor receiving\n");
2667                 goto err_udev_monitor;
2668         }
2669
2670         udev_device_unref(drm_device);
2671
2672         weston_compositor_add_debug_binding(&ec->base, KEY_O,
2673                                             planes_binding, ec);
2674         weston_compositor_add_debug_binding(&ec->base, KEY_C,
2675                                             planes_binding, ec);
2676         weston_compositor_add_debug_binding(&ec->base, KEY_V,
2677                                             planes_binding, ec);
2678         weston_compositor_add_debug_binding(&ec->base, KEY_Q,
2679                                             recorder_binding, ec);
2680
2681         return &ec->base;
2682
2683 err_udev_monitor:
2684         wl_event_source_remove(ec->udev_drm_source);
2685         udev_monitor_unref(ec->udev_monitor);
2686 err_drm_source:
2687         wl_event_source_remove(ec->drm_source);
2688         udev_input_destroy(&ec->input);
2689 err_sprite:
2690         ec->base.renderer->destroy(&ec->base);
2691         gbm_device_destroy(ec->gbm);
2692         destroy_sprites(ec);
2693 err_udev_dev:
2694         udev_device_unref(drm_device);
2695 err_tty:
2696         if (weston_launcher_drm_set_master(&ec->base, ec->drm.fd, 0) < 0)
2697                 weston_log("failed to drop master: %m\n");
2698         tty_destroy(ec->tty);
2699 err_udev:
2700         udev_unref(ec->udev);
2701 err_compositor:
2702         weston_compositor_shutdown(&ec->base);
2703 err_base:
2704         free(ec);
2705         return NULL;
2706 }
2707
2708 WL_EXPORT struct weston_compositor *
2709 backend_init(struct wl_display *display, int *argc, char *argv[],
2710              struct weston_config *config)
2711 {
2712         int connector = 0, tty = 0, use_pixman = 0;
2713         const char *seat_id = default_seat;
2714
2715         const struct weston_option drm_options[] = {
2716                 { WESTON_OPTION_INTEGER, "connector", 0, &connector },
2717                 { WESTON_OPTION_STRING, "seat", 0, &seat_id },
2718                 { WESTON_OPTION_INTEGER, "tty", 0, &tty },
2719                 { WESTON_OPTION_BOOLEAN, "current-mode", 0, &option_current_mode },
2720                 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &use_pixman },
2721         };
2722
2723         parse_options(drm_options, ARRAY_LENGTH(drm_options), argc, argv);
2724
2725         return drm_compositor_create(display, connector, seat_id, tty, use_pixman,
2726                                      argc, argv, config);
2727 }