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