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