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