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