Drop libdrm CFLAGS where no longer necessary.
[profile/ivi/wayland.git] / wayland-system-compositor.c
1 /*
2  * Copyright © 2008 Kristian Høgsberg
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdbool.h>
22 #include <stdlib.h>
23 #include <stdint.h>
24 #include <stdarg.h>
25 #include <termios.h>
26 #include <i915_drm.h>
27 #include <sys/ioctl.h>
28 #include <sys/mman.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <signal.h>
32 #include <cairo.h>
33 #include <gdk-pixbuf/gdk-pixbuf.h>
34 #include <glib.h>
35 #include <sys/poll.h>
36 #include <png.h>
37 #include <math.h>
38 #include <linux/input.h>
39 #include <linux/vt.h>
40 #include <xf86drmMode.h>
41 #include <time.h>
42 #include <fnmatch.h>
43 #include <dirent.h>
44
45 #define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE
46 #include <libudev.h>
47
48 #include <GL/gl.h>
49 #include <eagle.h>
50
51 #include "wayland.h"
52 #include "wayland-protocol.h"
53 #include "cairo-util.h"
54 #include "wayland-system-compositor.h"
55
56 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
57
58 struct wl_visual {
59         struct wl_object base;
60 };
61
62 struct wlsc_output {
63         struct wl_object base;
64         struct wl_list link;
65         struct egl_compositor *ec;
66         struct egl_surface *background;
67         EGLSurface surface;
68         int32_t x, y, width, height, stride;
69
70         struct drm_mode_modeinfo *mode;
71         uint32_t fb_id;
72         uint32_t crtc_id;
73         uint32_t connector_id;
74 };
75
76 struct wlsc_input_device {
77         struct wl_object base;
78         int32_t x, y;
79         struct egl_compositor *ec;
80         struct egl_surface *pointer_surface;
81         struct wl_list link;
82
83         int grab;
84         struct egl_surface *grab_surface;
85         struct egl_surface *focus_surface;
86 };
87
88 struct egl_compositor {
89         struct wl_compositor base;
90         struct wl_visual argb_visual, premultiplied_argb_visual, rgb_visual;
91
92         EGLDisplay display;
93         EGLContext context;
94         EGLConfig config;
95         struct wl_display *wl_display;
96
97         struct wl_list output_list;
98         struct wl_list input_device_list;
99         struct wl_list surface_list;
100
101         struct wl_event_source *term_signal_source;
102
103         /* tty handling state */
104         int tty_fd;
105         uint32_t vt_active : 1;
106
107         struct termios terminal_attributes;
108         struct wl_event_source *tty_input_source;
109         struct wl_event_source *enter_vt_source;
110         struct wl_event_source *leave_vt_source;
111
112         struct udev *udev;
113
114         /* Repaint state. */
115         struct wl_event_source *timer_source;
116         int repaint_needed;
117         int repaint_on_timeout;
118         struct timespec previous_swap;
119         uint32_t current_frame;
120 };
121
122 struct egl_surface {
123         struct wl_surface base;
124         struct egl_compositor *compositor;
125         struct wl_visual *visual;
126         GLuint texture;
127         struct wl_map map;
128         EGLSurface surface;
129         int width, height;
130         struct wl_list link;
131 };
132
133 static const char *option_background = "background.jpg";
134
135 static const GOptionEntry option_entries[] = {
136         { "background", 'b', 0, G_OPTION_ARG_STRING,
137           &option_background, "Background image" },
138         { NULL }
139 };
140
141
142 struct screenshooter {
143         struct wl_object base;
144         struct egl_compositor *ec;
145 };
146
147 struct screenshooter_interface {
148         void (*shoot)(struct wl_client *client, struct screenshooter *shooter);
149 };
150
151 static void
152 screenshooter_shoot(struct wl_client *client, struct screenshooter *shooter)
153 {
154         struct egl_compositor *ec = shooter->ec;
155         struct wlsc_output *output;
156         GLuint stride;
157         char buffer[256];
158         GdkPixbuf *pixbuf;
159         GError *error = NULL;
160         void *data;
161         int i;
162
163         i = 0;
164         output = container_of(ec->output_list.next, struct wlsc_output, link);
165         while (&output->link != &ec->output_list) {
166                 snprintf(buffer, sizeof buffer, "wayland-screenshot-%d.png", i++);
167                 data = eglReadBuffer(ec->display, output->surface, GL_FRONT_LEFT, &stride);
168                 pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, TRUE,
169                                                   8, output->width, output->height, stride,
170                                                   NULL, NULL);
171                 gdk_pixbuf_save(pixbuf, buffer, "png", &error, NULL);
172
173                 output = container_of(output->link.next,
174                                       struct wlsc_output, link);
175         }
176 }
177
178 static const struct wl_message screenshooter_methods[] = {
179         { "shoot", "", NULL }
180 };
181
182 static const struct wl_interface screenshooter_interface = {
183         "screenshooter", 1,
184         ARRAY_LENGTH(screenshooter_methods),
185         screenshooter_methods,
186 };
187
188 struct screenshooter_interface screenshooter_implementation = {
189         screenshooter_shoot
190 };
191
192 static struct screenshooter *
193 screenshooter_create(struct egl_compositor *ec)
194 {
195         struct screenshooter *shooter;
196
197         shooter = malloc(sizeof *shooter);
198         if (shooter == NULL)
199                 return NULL;
200
201         shooter->base.interface = &screenshooter_interface;
202         shooter->base.implementation = (void(**)(void)) &screenshooter_implementation;
203         shooter->ec = ec;
204
205         return shooter;
206 };
207
208 static struct egl_surface *
209 egl_surface_create_from_cairo_surface(struct egl_compositor *ec,
210                                       cairo_surface_t *surface,
211                                       int x, int y, int width, int height)
212 {
213         struct egl_surface *es;
214         int stride;
215         void *data;
216
217         stride = cairo_image_surface_get_stride(surface);
218         data = cairo_image_surface_get_data(surface);
219
220         es = malloc(sizeof *es);
221         if (es == NULL)
222                 return NULL;
223
224         glGenTextures(1, &es->texture);
225         glBindTexture(GL_TEXTURE_2D, es->texture);
226         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
227         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT);
228         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
229         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
230         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
231                      GL_BGRA, GL_UNSIGNED_BYTE, data);
232
233         es->compositor = ec;
234         es->map.x = x;
235         es->map.y = y;
236         es->map.width = width;
237         es->map.height = height;
238         es->surface = EGL_NO_SURFACE;
239         es->visual = &ec->premultiplied_argb_visual;
240
241         return es;
242 }
243
244 static void
245 egl_surface_destroy(struct egl_surface *es, struct egl_compositor *ec)
246 {
247         glDeleteTextures(1, &es->texture);
248         if (es->surface != EGL_NO_SURFACE)
249                 eglDestroySurface(ec->display, es->surface);
250         free(es);
251 }
252
253 static void
254 pointer_path(cairo_t *cr, int x, int y)
255 {
256         const int end = 3, tx = 4, ty = 12, dx = 5, dy = 10;
257         const int width = 16, height = 16;
258
259         cairo_move_to(cr, x, y);
260         cairo_line_to(cr, x + tx, y + ty);
261         cairo_line_to(cr, x + dx, y + dy);
262         cairo_line_to(cr, x + width - end, y + height);
263         cairo_line_to(cr, x + width, y + height - end);
264         cairo_line_to(cr, x + dy, y + dx);
265         cairo_line_to(cr, x + ty, y + tx);
266         cairo_close_path(cr);
267 }
268
269 static struct egl_surface *
270 pointer_create(struct egl_compositor *ec, int x, int y, int width, int height)
271 {
272         struct egl_surface *es;
273         const int hotspot_x = 16, hotspot_y = 16;
274         cairo_surface_t *surface;
275         cairo_t *cr;
276
277         surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
278                                              width, height);
279
280         cr = cairo_create(surface);
281         pointer_path(cr, hotspot_x + 5, hotspot_y + 4);
282         cairo_set_line_width(cr, 2);
283         cairo_set_source_rgb(cr, 0, 0, 0);
284         cairo_stroke_preserve(cr);
285         cairo_fill(cr);
286         blur_surface(surface, width);
287
288         pointer_path(cr, hotspot_x, hotspot_y);
289         cairo_stroke_preserve(cr);
290         cairo_set_source_rgb(cr, 1, 1, 1);
291         cairo_fill(cr);
292         cairo_destroy(cr);
293
294         es = egl_surface_create_from_cairo_surface(ec,
295                                                    surface,
296                                                    x - hotspot_x,
297                                                    y - hotspot_y,
298                                                    width, height);
299         
300         cairo_surface_destroy(surface);
301
302         return es;
303 }
304
305 static struct egl_surface *
306 background_create(struct wlsc_output *output, const char *filename)
307 {
308         struct egl_surface *background;
309         GdkPixbuf *pixbuf;
310         GError *error = NULL;
311         void *data;
312         GLenum format;
313
314         background = malloc(sizeof *background);
315         if (background == NULL)
316                 return NULL;
317         
318         g_type_init();
319
320         pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
321                                                    output->width,
322                                                    output->height,
323                                                    FALSE, &error);
324         if (error != NULL) {
325                 free(background);
326                 return NULL;
327         }
328
329         data = gdk_pixbuf_get_pixels(pixbuf);
330
331         glGenTextures(1, &background->texture);
332         glBindTexture(GL_TEXTURE_2D, background->texture);
333         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
334         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT);
335         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
336         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
337
338         if (gdk_pixbuf_get_has_alpha(pixbuf))
339                 format = GL_RGBA;
340         else
341                 format = GL_RGB;
342
343         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
344                      output->width, output->height, 0,
345                      format, GL_UNSIGNED_BYTE, data);
346
347         background->compositor = output->ec;
348         background->map.x = output->x;
349         background->map.y = output->y;
350         background->map.width = output->width;
351         background->map.height = output->height;
352         background->surface = EGL_NO_SURFACE;
353         background->visual = &output->ec->rgb_visual;
354
355         return background;
356 }
357
358 static void
359 draw_surface(struct egl_surface *es)
360 {
361         struct egl_compositor *ec = es->compositor;
362         GLint vertices[12];
363         GLint tex_coords[12] = { 0, 0,  0, 1,  1, 0,  1, 1 };
364         GLuint indices[4] = { 0, 1, 2, 3 };
365
366         vertices[0] = es->map.x;
367         vertices[1] = es->map.y;
368         vertices[2] = 0;
369
370         vertices[3] = es->map.x;
371         vertices[4] = es->map.y + es->map.height;
372         vertices[5] = 0;
373
374         vertices[6] = es->map.x + es->map.width;
375         vertices[7] = es->map.y;
376         vertices[8] = 0;
377
378         vertices[9] = es->map.x + es->map.width;
379         vertices[10] = es->map.y + es->map.height;
380         vertices[11] = 0;
381
382         if (es->visual == &ec->argb_visual) {
383                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
384                 glEnable(GL_BLEND);
385         } else if (es->visual == &ec->premultiplied_argb_visual) {
386                 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
387                 glEnable(GL_BLEND);
388         } else {
389                 glDisable(GL_BLEND);
390         }
391
392         glBindTexture(GL_TEXTURE_2D, es->texture);
393         glEnable(GL_TEXTURE_2D);
394         glEnableClientState(GL_VERTEX_ARRAY);
395         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
396         glVertexPointer(3, GL_INT, 0, vertices);
397         glTexCoordPointer(2, GL_INT, 0, tex_coords);
398         glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, indices);
399 }
400
401 static void
402 repaint_output(struct wlsc_output *output)
403 {
404         struct egl_compositor *ec = output->ec;
405         struct egl_surface *es;
406         struct wlsc_input_device *eid;
407
408         if (!eglMakeCurrent(ec->display, output->surface, output->surface, ec->context)) {
409                 fprintf(stderr, "failed to make context current\n");
410                 return;
411         }
412
413         glViewport(0, 0, output->width, output->height);
414         glMatrixMode(GL_PROJECTION);
415         glLoadIdentity();
416         glOrtho(0, output->width, output->height, 0, 0, 1000.0);
417         glMatrixMode(GL_MODELVIEW);
418         glClearColor(0, 0, 0.2, 1);
419
420         if (output->background)
421                 draw_surface(output->background);
422         else
423                 glClear(GL_COLOR_BUFFER_BIT);
424
425         es = container_of(ec->surface_list.next,
426                           struct egl_surface, link);
427         while (&es->link != &ec->surface_list) {
428                 draw_surface(es);
429
430                 es = container_of(es->link.next,
431                                    struct egl_surface, link);
432         }
433
434         eid = container_of(ec->input_device_list.next,
435                            struct wlsc_input_device, link);
436         while (&eid->link != &ec->input_device_list) {
437                 draw_surface(eid->pointer_surface);
438
439                 eid = container_of(eid->link.next,
440                                    struct wlsc_input_device, link);
441         }
442
443         eglSwapBuffers(ec->display, output->surface);
444 }
445
446 static void
447 repaint(void *data)
448 {
449         struct egl_compositor *ec = data;
450         struct wlsc_output *output;
451         struct timespec ts;
452         uint32_t msecs;
453
454         if (!ec->repaint_needed) {
455                 ec->repaint_on_timeout = 0;
456                 return;
457         }
458
459         output = container_of(ec->output_list.next, struct wlsc_output, link);
460         while (&output->link != &ec->output_list) {
461                 repaint_output(output);
462                 output = container_of(output->link.next,
463                                       struct wlsc_output, link);
464         }
465
466         ec->repaint_needed = 0;
467
468         clock_gettime(CLOCK_MONOTONIC, &ts);
469         msecs = ts.tv_sec * 1000 + ts.tv_nsec / (1000 * 1000);
470         wl_display_post_frame(ec->wl_display, &ec->base,
471                               ec->current_frame, msecs);
472         ec->current_frame++;
473
474         wl_event_source_timer_update(ec->timer_source, 10);
475         ec->repaint_on_timeout = 1;
476 }
477
478 static void
479 schedule_repaint(struct egl_compositor *ec)
480 {
481         struct wl_event_loop *loop;
482
483         ec->repaint_needed = 1;
484         if (!ec->repaint_on_timeout) {
485                 loop = wl_display_get_event_loop(ec->wl_display);
486                 wl_event_loop_add_idle(loop, repaint, ec);
487         }
488 }
489                                    
490 static void
491 surface_destroy(struct wl_client *client,
492                 struct wl_surface *surface)
493 {
494         struct egl_surface *es = (struct egl_surface *) surface;
495         struct egl_compositor *ec = es->compositor;
496
497         wl_list_remove(&es->link);
498         egl_surface_destroy(es, ec);
499
500         schedule_repaint(ec);
501 }
502
503 static void
504 surface_attach(struct wl_client *client,
505                struct wl_surface *surface, uint32_t name, 
506                uint32_t width, uint32_t height, uint32_t stride,
507                struct wl_object *visual)
508 {
509         struct egl_surface *es = (struct egl_surface *) surface;
510         struct egl_compositor *ec = es->compositor;
511
512         if (es->surface != EGL_NO_SURFACE)
513                 eglDestroySurface(ec->display, es->surface);
514
515         es->width = width;
516         es->height = height;
517         es->surface = eglCreateSurfaceForName(ec->display, ec->config,
518                                               name, width, height, stride, NULL);
519         if (visual == &ec->argb_visual.base)
520                 es->visual = &ec->argb_visual;
521         else if (visual == &ec->premultiplied_argb_visual.base)
522                 es->visual = &ec->premultiplied_argb_visual;
523         else if (visual == &ec->rgb_visual.base)
524                 es->visual = &ec->rgb_visual;
525         else
526                 /* FIXME: Smack client with an exception event */;
527
528         glBindTexture(GL_TEXTURE_2D, es->texture);
529         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
530         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT);
531         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
532         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
533         eglBindTexImage(ec->display, es->surface, GL_TEXTURE_2D);
534 }
535
536 static void
537 surface_map(struct wl_client *client,
538             struct wl_surface *surface,
539             int32_t x, int32_t y, int32_t width, int32_t height)
540 {
541         struct egl_surface *es = (struct egl_surface *) surface;
542
543         es->map.x = x;
544         es->map.y = y;
545         es->map.width = width;
546         es->map.height = height;
547 }
548
549 static void
550 surface_copy(struct wl_client *client,
551              struct wl_surface *surface,
552              int32_t dst_x, int32_t dst_y,
553              uint32_t name, uint32_t stride,
554              int32_t x, int32_t y, int32_t width, int32_t height)
555 {
556         struct egl_surface *es = (struct egl_surface *) surface;
557         struct egl_compositor *ec = es->compositor;
558         EGLSurface src;
559
560         /* FIXME: glCopyPixels should work, but then we'll have to
561          * call eglMakeCurrent to set up the src and dest surfaces
562          * first.  This seems cheaper, but maybe there's a better way
563          * to accomplish this. */
564
565         src = eglCreateSurfaceForName(ec->display, ec->config,
566                                       name, x + width, y + height, stride, NULL);
567
568         eglCopyNativeBuffers(ec->display, es->surface, GL_FRONT_LEFT, dst_x, dst_y,
569                              src, GL_FRONT_LEFT, x, y, width, height);
570         eglDestroySurface(ec->display, src);
571 }
572
573 static void
574 surface_damage(struct wl_client *client,
575                struct wl_surface *surface,
576                int32_t x, int32_t y, int32_t width, int32_t height)
577 {
578         /* FIXME: This need to take a damage region, of course. */
579 }
580
581 const static struct wl_surface_interface surface_interface = {
582         surface_destroy,
583         surface_attach,
584         surface_map,
585         surface_copy,
586         surface_damage
587 };
588
589 static void
590 compositor_create_surface(struct wl_client *client,
591                           struct wl_compositor *compositor, uint32_t id)
592 {
593         struct egl_compositor *ec = (struct egl_compositor *) compositor;
594         struct egl_surface *es;
595
596         es = malloc(sizeof *es);
597         if (es == NULL)
598                 /* FIXME: Send OOM event. */
599                 return;
600
601         es->compositor = ec;
602         es->surface = EGL_NO_SURFACE;
603         wl_list_insert(ec->surface_list.prev, &es->link);
604         glGenTextures(1, &es->texture);
605         wl_client_add_surface(client, &es->base,
606                               &surface_interface, id);
607 }
608
609 static void
610 compositor_commit(struct wl_client *client,
611                   struct wl_compositor *compositor, uint32_t key)
612 {
613         struct egl_compositor *ec = (struct egl_compositor *) compositor;
614
615         schedule_repaint(ec);
616         wl_client_send_acknowledge(client, compositor, key, ec->current_frame);
617 }
618
619 const static struct wl_compositor_interface compositor_interface = {
620         compositor_create_surface,
621         compositor_commit
622 };
623
624 static struct egl_surface *
625 pick_surface(struct wlsc_input_device *device, int32_t *sx, int32_t *sy)
626 {
627         struct egl_compositor *ec = device->ec;
628         struct egl_surface *es;
629
630         if (device->grab > 0)
631                 return device->grab_surface;
632
633         es = container_of(ec->surface_list.prev,
634                           struct egl_surface, link);
635         while (&es->link != &ec->surface_list) {
636                 if (es->map.x <= device->x &&
637                     device->x < es->map.x + es->map.width &&
638                     es->map.y <= device->y &&
639                     device->y < es->map.y + es->map.height)
640                         return es;
641
642                 es = container_of(es->link.prev,
643                                   struct egl_surface, link);
644
645                 /* Transform to surface coordinates. */
646                 *sx = (device->x - es->map.x) * es->width / es->map.width;
647                 *sy = (device->y - es->map.y) * es->height / es->map.height;
648         }
649
650         return NULL;
651 }
652
653 void
654 notify_motion(struct wlsc_input_device *device, int x, int y)
655 {
656         struct egl_surface *es;
657         struct egl_compositor *ec = device->ec;
658         struct wlsc_output *output;
659         const int hotspot_x = 16, hotspot_y = 16;
660         int32_t sx, sy;
661
662         if (!ec->vt_active)
663                 return;
664
665         /* FIXME: We need some multi head love here. */
666         output = container_of(ec->output_list.next, struct wlsc_output, link);
667         if (x < output->x)
668                 x = 0;
669         if (y < output->y)
670                 y = 0;
671         if (x >= output->x + output->width)
672                 x = output->x + output->width - 1;
673         if (y >= output->y + output->height)
674                 y = output->y + output->height - 1;
675
676         device->x = x;
677         device->y = y;
678         es = pick_surface(device, &sx, &sy);
679         if (es)
680                 wl_surface_post_event(&es->base, &device->base,
681                                       WL_INPUT_MOTION, x, y, sx, sy);
682
683         device->pointer_surface->map.x = x - hotspot_x;
684         device->pointer_surface->map.y = y - hotspot_y;
685
686         schedule_repaint(device->ec);
687 }
688
689 void
690 notify_button(struct wlsc_input_device *device,
691               int32_t button, int32_t state)
692 {
693         struct egl_surface *es;
694         struct egl_compositor *ec = device->ec;
695         int32_t sx, sy;
696
697         if (!ec->vt_active)
698                 return;
699
700         es = pick_surface(device, &sx, &sy);
701         if (es) {
702                 wl_list_remove(&es->link);
703                 wl_list_insert(device->ec->surface_list.prev, &es->link);
704
705                 if (state) {
706                         /* FIXME: We need callbacks when the surfaces
707                          * we reference here go away. */
708                         device->grab++;
709                         device->grab_surface = es;
710                         device->focus_surface = es;
711                 } else {
712                         device->grab--;
713                 }
714
715                 /* FIXME: Swallow click on raise? */
716                 wl_surface_post_event(&es->base, &device->base,
717                                       WL_INPUT_BUTTON, button, state,
718                                       device->x, device->y, sx, sy);
719
720                 schedule_repaint(device->ec);
721         }
722 }
723
724 void
725 notify_key(struct wlsc_input_device *device,
726            uint32_t key, uint32_t state)
727 {
728         struct egl_compositor *ec = device->ec;
729
730         if (!ec->vt_active)
731                 return;
732
733         if (device->focus_surface != NULL)
734                 wl_surface_post_event(&device->focus_surface->base,
735                                       &device->base, 
736                                       WL_INPUT_KEY, key, state);
737 }
738
739 struct evdev_input_device *
740 evdev_input_device_create(struct wlsc_input_device *device,
741                           struct wl_display *display, const char *path);
742
743 static struct wlsc_input_device *
744 create_input_device(struct egl_compositor *ec)
745 {
746         struct wlsc_input_device *device;
747
748         device = malloc(sizeof *device);
749         if (device == NULL)
750                 return NULL;
751
752         memset(device, 0, sizeof *device);
753         device->base.interface = &wl_input_device_interface;
754         device->base.implementation = NULL;
755         wl_display_add_object(ec->wl_display, &device->base);
756         wl_display_add_global(ec->wl_display, &device->base, NULL);
757         device->x = 100;
758         device->y = 100;
759         device->ec = ec;
760
761         wl_list_insert(ec->input_device_list.prev, &device->link);
762
763         return device;
764 }
765
766 void
767 wlsc_device_get_position(struct wlsc_input_device *device, int32_t *x, int32_t *y)
768 {
769         *x = device->x;
770         *y = device->y;
771 }
772
773 static void
774 post_output_geometry(struct wl_client *client, struct wl_object *global)
775 {
776         struct wlsc_output *output =
777                 container_of(global, struct wlsc_output, base);
778
779         wl_client_post_event(client, global,
780                              WL_OUTPUT_GEOMETRY,
781                              output->width, output->height);
782 }
783
784 static const char *
785 get_udev_property(struct udev_device *device, const char *name)
786 {
787         struct udev_list_entry *entry;
788
789         udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(device))
790                 if (strcmp(udev_list_entry_get_name(entry), name) == 0)
791                         return udev_list_entry_get_value(entry);
792
793         return NULL;
794 }
795
796 static int
797 init_egl(struct egl_compositor *ec, struct udev_device *device)
798 {
799         static const EGLint config_attribs[] = {
800                 EGL_DEPTH_SIZE, 0,
801                 EGL_STENCIL_SIZE, 0,
802                 EGL_CONFIG_CAVEAT, EGL_NONE,
803                 EGL_NONE                
804         };
805
806         EGLint major, minor;
807
808         ec->display = eglCreateDisplayNative(device);
809         if (ec->display == NULL) {
810                 fprintf(stderr, "failed to create display\n");
811                 return -1;
812         }
813
814         if (!eglInitialize(ec->display, &major, &minor)) {
815                 fprintf(stderr, "failed to initialize display\n");
816                 return -1;
817         }
818
819         if (!eglChooseConfig(ec->display, config_attribs, &ec->config, 1, NULL))
820                 return -1;
821
822         ec->context = eglCreateContext(ec->display, ec->config, NULL, NULL);
823         if (ec->context == NULL) {
824                 fprintf(stderr, "failed to create context\n");
825                 return -1;
826         }
827         return 0;
828 }
829
830 static int
831 create_output(struct egl_compositor *ec, struct udev_device *device)
832 {
833         const static EGLint surface_attribs[] = {
834                 EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
835                 EGL_NONE
836         };
837
838         drmModeConnector *connector;
839         drmModeRes *resources;
840         drmModeEncoder *encoder;
841         struct drm_mode_modeinfo *mode;
842         struct drm_i915_gem_create create;
843         struct drm_gem_flink flink;
844         struct wlsc_output *output;
845         int i, ret, fd;
846
847         if (ec->display == NULL && init_egl(ec, device) < 0) {
848                 fprintf(stderr, "failed to initialize egl\n");
849                 return -1;
850         }
851
852         output = malloc(sizeof *output);
853         if (output == NULL)
854                 return -1;
855
856         fd = eglGetDisplayFD(ec->display);
857         resources = drmModeGetResources(fd);
858         if (!resources) {
859                 fprintf(stderr, "drmModeGetResources failed\n");
860                 return -1;
861         }
862
863         for (i = 0; i < resources->count_connectors; i++) {
864                 connector = drmModeGetConnector(fd, resources->connectors[i]);
865                 if (connector == NULL)
866                         continue;
867
868                 if (connector->connection == DRM_MODE_CONNECTED &&
869                     connector->count_modes > 0)
870                         break;
871
872                 drmModeFreeConnector(connector);
873         }
874
875         if (i == resources->count_connectors) {
876                 fprintf(stderr, "No currently active connector found.\n");
877                 return -1;
878         }
879
880         mode = &connector->modes[0];
881
882         for (i = 0; i < resources->count_encoders; i++) {
883                 encoder = drmModeGetEncoder(fd, resources->encoders[i]);
884
885                 if (encoder == NULL)
886                         continue;
887
888                 if (encoder->encoder_id == connector->encoder_id)
889                         break;
890
891                 drmModeFreeEncoder(encoder);
892         }
893
894         /* Mode size at 32 bpp */
895         create.size = mode->hdisplay * mode->vdisplay * 4;
896         if (ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create) != 0) {
897                 fprintf(stderr, "gem create failed: %m\n");
898                 return -1;
899         }
900
901         ret = drmModeAddFB(fd, mode->hdisplay, mode->vdisplay,
902                            32, 32, mode->hdisplay * 4, create.handle, &output->fb_id);
903         if (ret) {
904                 fprintf(stderr, "failed to add fb: %m\n");
905                 return -1;
906         }
907
908         ret = drmModeSetCrtc(fd, encoder->crtc_id, output->fb_id, 0, 0,
909                              &connector->connector_id, 1, mode);
910         if (ret) {
911                 fprintf(stderr, "failed to set mode: %m\n");
912                 return -1;
913         }
914
915         flink.handle = create.handle;
916         if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) != 0) {
917                 fprintf(stderr, "gem flink failed: %m\n");
918                 return -1;
919         }
920
921         output->ec = ec;
922         output->crtc_id = encoder->crtc_id;
923         output->connector_id = connector->connector_id;
924         output->mode = mode;
925         output->x = 0;
926         output->y = 0;
927         output->width = mode->hdisplay;
928         output->height = mode->vdisplay;
929         output->stride = mode->hdisplay * 4;
930
931         output->surface = eglCreateSurfaceForName(ec->display, ec->config,
932                                                   flink.name,
933                                                   output->width, output->height,
934                                                   output->stride,
935                                                   surface_attribs);
936         if (output->surface == NULL) {
937                 fprintf(stderr, "failed to create surface\n");
938                 return -1;
939         }
940
941         output->base.interface = &wl_output_interface;
942         wl_display_add_object(ec->wl_display, &output->base);
943         wl_display_add_global(ec->wl_display, &output->base, post_output_geometry);
944         wl_list_insert(ec->output_list.prev, &output->link);
945
946         if (!eglMakeCurrent(ec->display, output->surface, output->surface, ec->context)) {
947                 fprintf(stderr, "failed to make context current\n");
948                 return -1;
949         }
950
951         output->background = background_create(output, option_background);
952
953         return 0;
954 }
955
956 static const struct wl_interface visual_interface = {
957         "visual", 1,
958 };
959
960 static void
961 add_visuals(struct egl_compositor *ec)
962 {
963         ec->argb_visual.base.interface = &visual_interface;
964         ec->argb_visual.base.implementation = NULL;
965         wl_display_add_object(ec->wl_display, &ec->argb_visual.base);
966         wl_display_add_global(ec->wl_display, &ec->argb_visual.base, NULL);
967
968         ec->premultiplied_argb_visual.base.interface = &visual_interface;
969         ec->premultiplied_argb_visual.base.implementation = NULL;
970         wl_display_add_object(ec->wl_display,
971                               &ec->premultiplied_argb_visual.base);
972         wl_display_add_global(ec->wl_display,
973                               &ec->premultiplied_argb_visual.base, NULL);
974
975         ec->rgb_visual.base.interface = &visual_interface;
976         ec->rgb_visual.base.implementation = NULL;
977         wl_display_add_object(ec->wl_display, &ec->rgb_visual.base);
978         wl_display_add_global(ec->wl_display, &ec->rgb_visual.base, NULL);
979 }
980
981 static void on_enter_vt(int signal_number, void *data)
982 {
983         struct egl_compositor *ec = data;
984         struct wlsc_output *output;
985         int ret, fd;
986
987         ioctl(ec->tty_fd, VT_RELDISP, VT_ACKACQ);
988         ec->vt_active = TRUE;
989
990         fd = eglGetDisplayFD(ec->display);
991         output = container_of(ec->output_list.next, struct wlsc_output, link);
992         while (&output->link != &ec->output_list) {
993                 ret = drmModeSetCrtc(fd, output->crtc_id, output->fb_id, 0, 0,
994                                      &output->connector_id, 1, output->mode);
995                 if (ret)
996                         fprintf(stderr, "failed to set mode for connector %d: %m\n",
997                                 output->connector_id);
998
999                 output = container_of(output->link.next,
1000                                       struct wlsc_output, link);
1001         }
1002 }
1003
1004 static void on_leave_vt(int signal_number, void *data)
1005 {
1006         struct egl_compositor *ec = data;
1007
1008         ioctl (ec->tty_fd, VT_RELDISP, 1);
1009         ec->vt_active = FALSE;
1010 }
1011
1012 static void
1013 on_tty_input(int fd, uint32_t mask, void *data)
1014 {
1015         struct egl_compositor *ec = data;
1016
1017         /* Ignore input to tty.  We get keyboard events from evdev
1018          */
1019         tcflush(ec->tty_fd, TCIFLUSH);
1020 }
1021
1022 static void on_term_signal(int signal_number, void *data)
1023 {
1024         struct egl_compositor *ec = data;
1025
1026         if (tcsetattr(ec->tty_fd, TCSANOW, &ec->terminal_attributes) < 0)
1027                 fprintf(stderr, "could not restore terminal to canonical mode\n");
1028
1029         exit(0);
1030 }
1031
1032 static int setup_tty(struct egl_compositor *ec, struct wl_event_loop *loop)
1033 {
1034         struct termios raw_attributes;
1035         struct vt_mode mode = { 0 };
1036
1037         ec->tty_fd = open("/dev/tty0", O_RDWR | O_NOCTTY);
1038         if (ec->tty_fd <= 0) {
1039                 fprintf(stderr, "failed to open active tty: %m\n");
1040                 return -1;
1041         }
1042
1043         if (tcgetattr(ec->tty_fd, &ec->terminal_attributes) < 0) {
1044                 fprintf(stderr, "could not get terminal attributes: %m\n");
1045                 return -1;
1046         }
1047
1048         /* Ignore control characters and disable echo */
1049         raw_attributes = ec->terminal_attributes;
1050         cfmakeraw(&raw_attributes);
1051
1052         /* Fix up line endings to be normal (cfmakeraw hoses them) */
1053         raw_attributes.c_oflag |= OPOST | OCRNL;
1054
1055         if (tcsetattr(ec->tty_fd, TCSANOW, &raw_attributes) < 0)
1056                 fprintf(stderr, "could not put terminal into raw mode: %m\n");
1057
1058         ec->term_signal_source =
1059                 wl_event_loop_add_signal(loop, SIGTERM, on_term_signal, ec);
1060
1061         ec->tty_input_source =
1062                 wl_event_loop_add_fd(loop, ec->tty_fd,
1063                                      WL_EVENT_READABLE, on_tty_input, ec);
1064
1065         ec->vt_active = TRUE;
1066         mode.mode = VT_PROCESS;
1067         mode.relsig = SIGUSR1;
1068         mode.acqsig = SIGUSR2;
1069         if (!ioctl(ec->tty_fd, VT_SETMODE, &mode) < 0) {
1070                 fprintf(stderr, "failed to take control of vt handling\n");
1071         }
1072
1073         ec->leave_vt_source =
1074                 wl_event_loop_add_signal(loop, SIGUSR1, on_leave_vt, ec);
1075         ec->enter_vt_source =
1076                 wl_event_loop_add_signal(loop, SIGUSR2, on_enter_vt, ec);
1077
1078         return 0;
1079 }
1080
1081 static int
1082 init_libudev(struct egl_compositor *ec)
1083 {
1084         struct udev_enumerate *e;
1085         struct udev_list_entry *entry;
1086         struct udev_device *device;
1087         const char *path, *seat;
1088         struct wlsc_input_device *input_device;
1089
1090         /* FIXME: Newer (version 135+) udev has two new features that
1091          * make all this much easier: 1) we can enumerate by a
1092          * specific property.  This lets us directly iterate through
1093          * the devices we care about. 2) We can attach properties to
1094          * sysfs nodes without a device file, which lets us configure
1095          * which connectors belong to a seat instead of tagging the
1096          * overall drm node.  I don't want to update my system udev,
1097          * so I'm going to stick with this until the new version is in
1098          * rawhide. */
1099
1100         ec->udev = udev_new();
1101         if (ec->udev == NULL) {
1102                 fprintf(stderr, "failed to initialize udev context\n");
1103                 return -1;
1104         }
1105
1106         input_device = create_input_device(ec);
1107
1108         e = udev_enumerate_new(ec->udev);
1109         udev_enumerate_scan_devices(e);
1110         udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
1111                 path = udev_list_entry_get_name(entry);
1112                 device = udev_device_new_from_syspath(ec->udev, path);
1113
1114                 /* FIXME: Should the property namespace be CK for console kit? */
1115                 seat = get_udev_property(device, "WAYLAND_SEAT");
1116                 if (!seat || strcmp(seat, "1") != 0)
1117                         continue;
1118
1119                 if (strcmp(udev_device_get_subsystem(device), "input") == 0) {
1120                         evdev_input_device_create(input_device, ec->wl_display,
1121                                                   udev_device_get_devnode(device));
1122                 } else if (strcmp(udev_device_get_subsystem(device), "drm") == 0) {
1123                         if (create_output(ec, device) < 0) {
1124                                 fprintf(stderr, "failed to create output for %s\n", path);
1125                                 return -1;
1126                         }
1127                 }
1128         }
1129         udev_enumerate_unref(e);
1130
1131         /* Create the pointer surface now that we have a current EGL context. */
1132         input_device->pointer_surface =
1133                 pointer_create(ec, input_device->x, input_device->y, 64, 64);
1134
1135         return 0;
1136 }
1137
1138 static struct egl_compositor *
1139 egl_compositor_create(struct wl_display *display)
1140 {
1141         struct egl_compositor *ec;
1142         struct screenshooter *shooter;
1143         struct wl_event_loop *loop;
1144
1145         ec = malloc(sizeof *ec);
1146         if (ec == NULL)
1147                 return NULL;
1148
1149         memset(ec, 0, sizeof *ec);
1150         ec->wl_display = display;
1151
1152         wl_display_set_compositor(display, &ec->base, &compositor_interface); 
1153
1154         add_visuals(ec);
1155
1156         wl_list_init(&ec->surface_list);
1157         wl_list_init(&ec->input_device_list);
1158         wl_list_init(&ec->output_list);
1159         if (init_libudev(ec) < 0) {
1160                 fprintf(stderr, "failed to initialize devices\n");
1161                 return NULL;
1162         }
1163
1164         shooter = screenshooter_create(ec);
1165         wl_display_add_object(display, &shooter->base);
1166         wl_display_add_global(display, &shooter->base, NULL);
1167
1168         loop = wl_display_get_event_loop(ec->wl_display);
1169
1170         setup_tty(ec, loop);
1171
1172         ec->timer_source = wl_event_loop_add_timer(loop, repaint, ec);
1173         schedule_repaint(ec);
1174
1175         return ec;
1176 }
1177
1178 /* The plan here is to generate a random anonymous socket name and
1179  * advertise that through a service on the session dbus.
1180  */
1181 static const char socket_name[] = "\0wayland";
1182
1183 int main(int argc, char *argv[])
1184 {
1185         struct wl_display *display;
1186         struct egl_compositor *ec;
1187         GError *error = NULL;
1188         GOptionContext *context;
1189
1190         context = g_option_context_new(NULL);
1191         g_option_context_add_main_entries(context, option_entries, "Wayland");
1192         if (!g_option_context_parse(context, &argc, &argv, &error)) {
1193                 fprintf(stderr, "option parsing failed: %s\n", error->message);
1194                 exit(EXIT_FAILURE);
1195         }
1196
1197         display = wl_display_create();
1198
1199         ec = egl_compositor_create(display);
1200         if (ec == NULL) {
1201                 fprintf(stderr, "failed to create compositor\n");
1202                 exit(EXIT_FAILURE);
1203         }
1204                 
1205         if (wl_display_add_socket(display, socket_name, sizeof socket_name)) {
1206                 fprintf(stderr, "failed to add socket: %m\n");
1207                 exit(EXIT_FAILURE);
1208         }
1209
1210         wl_display_run(display);
1211
1212         return 0;
1213 }