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