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