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