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