commit ba51fad

Michael Forney  ·  2013-01-15 10:44:00 +0000 UTC
parent ba51fad
Import
49 files changed,  +4191, -0
A drm.c
A drm.h
A egl.c
A egl.h
A mode.c
A mode.h
A seat.c
A seat.h
A tty.c
A tty.h
A util.c
A util.h
A xkb.c
A xkb.h
+25, -0
 1@@ -0,0 +1,25 @@
 2+*.o
 3+*.lo
 4+.*.swp
 5+
 6+.deps/
 7+.libs/
 8+
 9+Makefile
10+Makefile.in
11+
12+/aclocal.m4
13+/autom4te.cache/
14+/config.guess
15+/config.log
16+/config.status
17+/configure
18+/depcomp
19+/install-sh
20+/m4/
21+/missing
22+
23+/libswc.la
24+/i915/libi915.la
25+/testwm/testwm
26+
+33, -0
 1@@ -0,0 +1,33 @@
 2+# swc: Makefile.am
 3+
 4+ACLOCAL_AMFLAGS = -I m4
 5+
 6+noinst_LTLIBRARIES = libswc.la
 7+
 8+AM_CFLAGS = $(pixman_CFLAGS)
 9+
10+libswc_la_SOURCES = \
11+	compositor.c compositor.h \
12+	util.c util.h \
13+	output.c output.h \
14+	buffer.c buffer.h \
15+	surface.c surface.h \
16+	renderer.c renderer.h \
17+	seat.c seat.h \
18+	mode.c mode.h \
19+	tty.c tty.h \
20+	evdev_device.c evdev_device.h \
21+	xkb.c xkb.h \
22+	drm.c drm.h \
23+	egl.c egl.h
24+
25+libswc_la_LIBADD = $(wayland_server_LIBS) $(udev_LIBS) $(xkbcommon_LIBS) \
26+	$(drm_LIBS) $(gbm_LIBS) $(egl_LIBS) $(pixman_LIBS) i915/libi915.la
27+
28+# testclient_SOURCES = \
29+# 	testclient.c
30+# 
31+# testclient_LDADD = $(wayland_client_LIBS)
32+
33+SUBDIRS = i915 testwm
34+
+13, -0
 1@@ -0,0 +1,13 @@
 2+#!/bin/sh
 3+
 4+set -ex
 5+
 6+rm -rf autom4te.cache
 7+
 8+libtoolize
 9+aclocal -I m4 --force
10+autoconf -f -W all
11+automake -f -a -c -W all
12+
13+rm -rf autom4te.cache
14+
+8, -0
1@@ -0,0 +1,8 @@
2+#include "binding.h"
3+
4+bool swc_binding_init(struct wcf_binding * binding, uint32_t value,
5+                      uint32_t modifiers, wcf_binding_handler_t handler,
6+                      void * data)
7+{
8+}
9+
+25, -0
 1@@ -0,0 +1,25 @@
 2+#ifndef SWC_BINDING_H
 3+#define SWC_BINDING_H 1
 4+
 5+#include <stdint.h>
 6+#include <linux/input.h>
 7+
 8+#define MOD_CTRL    (1 << 0)
 9+#define MOD_ALT     (1 << 1)
10+#define MOD_SUPER   (1 << 2)
11+#define MOD_SHIFT   (1 << 3)
12+#define MOD_ANY     (-1)
13+
14+typedef void (* swc_binding_handler_t)(uint32_t time, uint32_t value,
15+                                       void * data);
16+
17+struct swc_binding
18+{
19+    uint32_t value;
20+    uint32_t modifiers;
21+    swc_binding_handler_t handler;
22+    void * data;
23+};
24+
25+#endif
26+
+98, -0
 1@@ -0,0 +1,98 @@
 2+#include "buffer.h"
 3+
 4+#include <stdio.h>
 5+#include <sys/mman.h>
 6+#include <libdrm/i915_drm.h>
 7+#include <xf86drm.h>
 8+#include <xf86drmMode.h>
 9+
10+/* Returns the next multiple of the eth power of 2 */
11+static inline uint32_t next_multiple_power_2(uint32_t n, uint32_t e)
12+{
13+    return (n + (1 << e) - 1) & ~((1 << e) - 1);
14+}
15+
16+static void destroy_image(pixman_image_t * image, void * data)
17+{
18+    struct swc_buffer * buffer = data;
19+
20+    munmap(pixman_image_get_data(image), buffer->bo.size);
21+}
22+
23+bool swc_buffer_initialize(struct swc_buffer * buffer, struct swc_drm * drm,
24+                           uint32_t width, uint32_t height)
25+{
26+    uint32_t size;
27+
28+    buffer->image = NULL;
29+
30+    buffer->width = width;
31+    buffer->height = height;
32+
33+    /* Round width up to next multiple of 512 */
34+    buffer->pitch = next_multiple_power_2(width * 4, 9);
35+
36+    /* Round height up to next multiple of 4 */
37+    size = buffer->pitch * next_multiple_power_2(height, 2);
38+
39+    printf("width: %u, height: %u, pitch: %u, size: %u\n", width, height, buffer->pitch, size);
40+
41+    i915_bo_initialize(drm->fd, &buffer->bo, size);
42+
43+    if (drmModeAddFB(drm->fd, width, height, 24, 32, buffer->pitch,
44+                     buffer->bo.handle, &buffer->id) != 0)
45+    {
46+        printf("could not create FB from buffer handle\n");
47+        goto error_buffer;
48+    }
49+
50+    return true;
51+
52+  error_buffer:
53+    {
54+        struct drm_gem_close close_arg = { .handle = buffer->bo.handle };
55+        drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &close_arg);
56+    }
57+  error_base:
58+    return false;
59+}
60+
61+void swc_buffer_finish(struct swc_buffer * buffer, struct swc_drm * drm)
62+{
63+    drmModeRmFB(drm->fd, buffer->id);
64+    i915_bo_finalize(drm->fd, &buffer->bo);
65+}
66+
67+void swc_buffer_ref_image(struct swc_buffer * buffer, struct swc_drm * drm)
68+{
69+    if (!buffer->image)
70+    {
71+        uint32_t * data;
72+        struct drm_i915_gem_mmap mmap_arg = {
73+            .handle = buffer->bo.handle,
74+            .size = buffer->bo.size
75+        };
76+
77+        if (drmCommandWriteRead(drm->fd, DRM_I915_GEM_MMAP, &mmap_arg,
78+                                sizeof mmap_arg) != 0)
79+        {
80+            printf("could not mmap buffer\n");
81+            return;
82+        }
83+
84+        data = (void *) mmap_arg.addr_ptr;
85+        buffer->image = pixman_image_create_bits(PIXMAN_x8r8g8b8,
86+                                                 buffer->width, buffer->height,
87+                                                 data, buffer->pitch);
88+        pixman_image_set_destroy_function(buffer->image, &destroy_image, buffer);
89+    }
90+    else
91+        pixman_image_ref(buffer->image);
92+}
93+
94+void swc_buffer_unref_image(struct swc_buffer * buffer)
95+{
96+    if (pixman_image_unref(buffer->image))
97+        buffer->image = NULL;
98+}
99+
+32, -0
 1@@ -0,0 +1,32 @@
 2+#ifndef SWC_BUFFER_H
 3+#define SWC_BUFFER_H 1
 4+
 5+#include "drm.h"
 6+#include "i915/bo.h"
 7+
 8+#include <stdbool.h>
 9+#include <pixman.h>
10+
11+struct swc_buffer
12+{
13+    uint32_t id;
14+
15+    struct i915_bo bo;
16+
17+    /* Pixman image using the mapped buffer for use with SHM. */
18+    pixman_image_t * image;
19+
20+    uint32_t width, height, pitch;
21+};
22+
23+bool swc_buffer_initialize(struct swc_buffer * buffer, struct swc_drm * drm,
24+                           uint32_t width, uint32_t height);
25+
26+void swc_buffer_finish(struct swc_buffer * buffer, struct swc_drm * drm);
27+
28+void swc_buffer_ref_image(struct swc_buffer * buffer, struct swc_drm * drm);
29+
30+void swc_buffer_unref_image(struct swc_buffer * buffer);
31+
32+#endif
33+
+405, -0
  1@@ -0,0 +1,405 @@
  2+#include <stdlib.h>
  3+#include <stdio.h>
  4+#include <libudev.h>
  5+#include <gbm.h>
  6+
  7+#include "compositor.h"
  8+#include "tty.h"
  9+#include "output.h"
 10+#include "surface.h"
 11+#include "event.h"
 12+
 13+const char default_seat[] = "seat0";
 14+
 15+struct repaint_operation
 16+{
 17+    struct swc_renderer * renderer;
 18+    struct swc_output * output;
 19+    struct wl_list * surfaces;
 20+};
 21+
 22+static void repaint_output(void * data)
 23+{
 24+    struct repaint_operation * operation = data;
 25+
 26+    swc_renderer_repaint_output(operation->renderer, operation->output,
 27+                                operation->surfaces);
 28+
 29+    swc_output_switch_buffer(operation->output);
 30+
 31+    /* XXX: should go in page flip handler */
 32+    operation->output->repaint_scheduled = false;
 33+
 34+    free(operation);
 35+}
 36+
 37+static void schedule_repaint_for_output(struct swc_compositor * compositor,
 38+                                        struct swc_output * output)
 39+{
 40+    struct wl_event_loop * event_loop;
 41+    struct repaint_operation * operation;
 42+
 43+    if (output->repaint_scheduled)
 44+        return;
 45+
 46+    operation = malloc(sizeof *operation);
 47+    operation->renderer = &compositor->renderer;
 48+    operation->output = output;
 49+    operation->surfaces = &compositor->surfaces;
 50+
 51+    event_loop = wl_display_get_event_loop(compositor->display);
 52+    wl_event_loop_add_idle(event_loop, &repaint_output, operation);
 53+    output->repaint_scheduled = true;
 54+}
 55+
 56+static void handle_key(struct wl_keyboard_grab * grab, uint32_t time,
 57+                       uint32_t key, uint32_t state)
 58+{
 59+    struct wl_keyboard * keyboard = grab->keyboard;
 60+    struct swc_seat * seat;
 61+    struct wl_resource * resource = keyboard->focus_resource;
 62+    struct swc_binding * binding;
 63+    struct swc_compositor * compositor;
 64+    char keysym_name[64];
 65+
 66+    seat = wl_container_of(keyboard, seat, keyboard);
 67+    compositor = wl_container_of(seat, compositor, seat);
 68+
 69+    if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
 70+    {
 71+        xkb_keysym_t keysym;
 72+
 73+        keysym = xkb_state_key_get_one_sym(seat->xkb.state, key + 8);
 74+
 75+        wl_array_for_each(binding, &compositor->key_bindings)
 76+        {
 77+            if (binding->value == keysym && (binding->modifiers == MOD_ANY
 78+                || binding->modifiers == seat->active_modifiers))
 79+            {
 80+                binding->handler(time, keysym, binding->data);
 81+                return;
 82+            }
 83+        }
 84+    }
 85+
 86+    if (resource)
 87+    {
 88+        struct wl_display * display;
 89+        uint32_t serial;
 90+
 91+        display = wl_client_get_display(resource->client);
 92+        serial = wl_display_next_serial(display);
 93+        wl_keyboard_send_key(resource, serial, time, key, state);
 94+    }
 95+}
 96+
 97+static void handle_modifiers(struct wl_keyboard_grab * grab, uint32_t serial,
 98+                             uint32_t mods_depressed, uint32_t mods_latched,
 99+                             uint32_t mods_locked, uint32_t group)
100+{
101+    //wl_keyboard_send_modifiers
102+}
103+
104+struct wl_keyboard_grab_interface binding_grab_interface = {
105+    .key = &handle_key,
106+    .modifiers = &handle_modifiers
107+};
108+
109+/* XXX: maybe this should go in swc_drm */
110+static void handle_tty_event(struct wl_listener * listener, void * data)
111+{
112+    struct swc_event * event = data;
113+    struct swc_compositor * compositor;
114+
115+    compositor = wl_container_of(listener, compositor, tty_listener);
116+
117+    switch (event->type)
118+    {
119+        case SWC_TTY_VT_ENTER:
120+            swc_drm_set_master(&compositor->drm);
121+            break;
122+        case SWC_TTY_VT_LEAVE:
123+            swc_drm_drop_master(&compositor->drm);
124+            break;
125+    }
126+}
127+
128+static void handle_surface_event(struct wl_listener * listener, void * data)
129+{
130+    struct swc_event * event = data;
131+    struct swc_surface * surface = event->data;
132+    struct swc_compositor * compositor = surface->compositor_state.compositor;
133+
134+    switch (event->type)
135+    {
136+        case SWC_SURFACE_ATTACH:
137+            swc_renderer_attach(&compositor->renderer, &compositor->outputs,
138+                                surface, surface->state.buffer);
139+            break;
140+        case SWC_SURFACE_REPAINT:
141+        {
142+            struct swc_output * output;
143+            wl_list_for_each(output, &compositor->outputs, link)
144+            {
145+                if (surface->output_mask & (1 << output->id))
146+                    schedule_repaint_for_output(compositor, output);
147+            }
148+            break;
149+        }
150+    }
151+}
152+
153+static void handle_drm_event(struct wl_listener * listener, void * data)
154+{
155+    struct swc_event * event = data;
156+    struct swc_compositor * compositor = wl_container_of(listener, compositor,
157+                                                         drm_listener);
158+}
159+
160+static void destroy_surface(struct wl_resource * resource)
161+{
162+    struct swc_surface * surface = resource->data;
163+
164+    free(surface);
165+}
166+
167+static void create_surface(struct wl_client * client,
168+                           struct wl_resource * resource, uint32_t id)
169+{
170+    printf("compositor_create_surface\n");
171+    struct swc_compositor * compositor = resource->data;
172+    struct swc_surface * surface;
173+    struct swc_output * output;
174+
175+    surface = malloc(sizeof *surface);
176+
177+    if (!surface)
178+    {
179+        wl_resource_post_no_memory(resource);
180+        return;
181+    }
182+
183+    output = wl_container_of(compositor->outputs.next, output, link);
184+
185+    /* Initialize compositor state */
186+    surface->compositor_state = (struct swc_compositor_surface_state) {
187+        .compositor = compositor,
188+        .event_listener = (struct wl_listener) {
189+            .notify = &handle_surface_event
190+        }
191+    };
192+
193+    swc_surface_initialize(surface);
194+    wl_signal_add(&surface->event_signal,
195+                  &surface->compositor_state.event_listener);
196+
197+    wl_list_insert(&compositor->surfaces, &surface->link);
198+    surface->output_mask |= 1 << output->id;
199+
200+    /* For some reason there is no Wayland method to initialize a preallocated
201+     * resource. */
202+    surface->wayland.resource = (struct wl_resource) {
203+        .object = {
204+            .interface = &wl_surface_interface,
205+            .implementation = (void (**)()) &swc_surface_interface,
206+            .id = id
207+        },
208+        .destroy = &destroy_surface,
209+        .data = surface
210+    };
211+
212+    wl_client_add_resource(client, &surface->wayland.resource);
213+}
214+
215+static void create_region(struct wl_client * client,
216+                          struct wl_resource * resource, uint32_t id)
217+{
218+}
219+
220+struct wl_compositor_interface compositor_implementation = {
221+    .create_surface = &create_surface,
222+    .create_region = &create_region
223+};
224+
225+static void bind_compositor(struct wl_client * client, void * data,
226+                            uint32_t version, uint32_t id)
227+{
228+    struct swc_compositor * compositor = data;
229+
230+    wl_client_add_object(client, &wl_compositor_interface,
231+                         &compositor_implementation, id, compositor);
232+}
233+
234+bool swc_compositor_initialize(struct swc_compositor * compositor,
235+                               struct wl_display * display)
236+{
237+    struct wl_event_loop * event_loop;
238+    struct udev_device * drm_device;
239+    struct wl_list * outputs;
240+
241+    if (compositor == NULL)
242+    {
243+        printf("could not allocate compositor\n");
244+        return NULL;
245+    }
246+
247+    compositor->display = display;
248+    compositor->tty_listener.notify = &handle_tty_event;
249+
250+    compositor->udev = udev_new();
251+
252+    if (compositor->udev == NULL)
253+    {
254+        printf("could not initialize udev context\n");
255+        goto error_base;
256+    }
257+
258+    event_loop = wl_display_get_event_loop(display);
259+
260+    if (!swc_tty_initialize(&compositor->tty, event_loop, 2))
261+    {
262+        printf("could not initialize tty\n");
263+        goto error_udev;
264+    }
265+
266+    wl_signal_add(&compositor->tty.event_signal, &compositor->tty_listener);
267+
268+    /* TODO: configurable seat */
269+    if (!swc_seat_initialize(&compositor->seat, compositor->udev,
270+                             default_seat))
271+    {
272+        printf("could not initialize seat\n");
273+        goto error_tty;
274+    }
275+
276+    swc_seat_add_event_sources(&compositor->seat, event_loop);
277+    compositor->seat.keyboard.default_grab.interface = &binding_grab_interface;
278+
279+    /* TODO: configurable seat */
280+    if (!swc_drm_initialize(&compositor->drm, compositor->udev, default_seat))
281+    {
282+        printf("could not initialize drm\n");
283+        goto error_seat;
284+    }
285+
286+    swc_drm_add_event_sources(&compositor->drm, event_loop);
287+
288+    compositor->gbm = gbm_create_device(compositor->drm.fd);
289+
290+    if (!compositor->gbm)
291+    {
292+        printf("could not create gbm device\n");
293+        goto error_drm;
294+    }
295+
296+    if (!swc_egl_initialize(&compositor->egl, compositor->gbm))
297+    {
298+        printf("could not initialize egl\n");
299+        goto error_gbm;
300+    }
301+
302+    if (!swc_egl_bind_display(&compositor->egl, compositor->display))
303+    {
304+        printf("could not bind egl display\n");
305+        swc_egl_finish(&compositor->egl);
306+        goto error_gbm;
307+    }
308+
309+    if (!swc_renderer_initialize(&compositor->renderer, &compositor->drm))
310+    {
311+        printf("could not initialize renderer\n");
312+        goto error_egl;
313+    }
314+
315+    outputs = swc_drm_create_outputs(&compositor->drm);
316+
317+    if (outputs)
318+    {
319+        wl_list_init(&compositor->outputs);
320+        wl_list_insert_list(&compositor->outputs, outputs);
321+        free(outputs);
322+    }
323+    else
324+    {
325+        printf("could not create outputs\n");
326+        goto error_renderer;
327+    }
328+
329+    wl_list_init(&compositor->surfaces);
330+    wl_array_init(&compositor->key_bindings);
331+    wl_signal_init(&compositor->destroy_signal);
332+
333+    return true;
334+
335+  error_renderer:
336+    swc_renderer_finalize(&compositor->renderer);
337+  error_egl:
338+    swc_egl_unbind_display(&compositor->egl, compositor->display);
339+    swc_egl_finish(&compositor->egl);
340+  error_gbm:
341+    gbm_device_destroy(compositor->gbm);
342+  error_drm:
343+    swc_drm_finish(&compositor->drm);
344+  error_seat:
345+    swc_seat_finish(&compositor->seat);
346+  error_tty:
347+    swc_tty_finish(&compositor->tty);
348+  error_udev:
349+    udev_unref(compositor->udev);
350+  error_base:
351+    free(compositor);
352+    return false;
353+}
354+
355+void swc_compositor_finish(struct swc_compositor * compositor)
356+{
357+    struct swc_output * output, * tmp;
358+
359+    wl_signal_emit(&compositor->destroy_signal, compositor);
360+
361+    wl_array_release(&compositor->key_bindings);
362+
363+    wl_list_for_each_safe(output, tmp, &compositor->outputs, link)
364+    {
365+        swc_output_finish(output);
366+        free(output);
367+    }
368+
369+    swc_egl_unbind_display(&compositor->egl, compositor->display);
370+    swc_egl_finish(&compositor->egl);
371+    gbm_device_destroy(compositor->gbm);
372+    swc_drm_finish(&compositor->drm);
373+    swc_seat_finish(&compositor->seat);
374+    swc_tty_finish(&compositor->tty);
375+    udev_unref(compositor->udev);
376+}
377+
378+void swc_compositor_add_globals(struct swc_compositor * compositor,
379+                                struct wl_display * display)
380+{
381+    struct swc_output * output;
382+
383+    wl_display_add_global(display, &wl_compositor_interface, compositor,
384+                          &bind_compositor);
385+
386+    swc_seat_add_globals(&compositor->seat, display);
387+
388+    wl_list_for_each(output, &compositor->outputs, link)
389+    {
390+        swc_output_add_globals(output, display);
391+    }
392+}
393+
394+void swc_compositor_add_key_binding(struct swc_compositor * compositor,
395+                                    uint32_t modifiers, uint32_t value,
396+                                    swc_binding_handler_t handler, void * data)
397+{
398+    struct swc_binding * binding;
399+
400+    binding = wl_array_add(&compositor->key_bindings, sizeof *binding);
401+    binding->value = value;
402+    binding->modifiers = modifiers;
403+    binding->handler = handler;
404+    binding->data = data;
405+}
406+
+50, -0
 1@@ -0,0 +1,50 @@
 2+#ifndef SWC_COMPOSITOR_H
 3+#define SWC_COMPOSITOR_H 1
 4+
 5+#include <wayland-server.h>
 6+
 7+#include "drm.h"
 8+#include "tty.h"
 9+#include "seat.h"
10+#include "egl.h"
11+#include "binding.h"
12+#include "event_listener.h"
13+#include "renderer.h"
14+
15+struct swc_compositor
16+{
17+    struct wl_display * display;
18+
19+    struct udev * udev;
20+    struct gbm_device * gbm;
21+
22+    struct swc_tty tty;
23+    struct swc_seat seat;
24+    struct swc_drm drm;
25+    struct swc_egl egl;
26+    struct swc_renderer renderer;
27+
28+    struct wl_list outputs;
29+    struct wl_list surfaces;
30+    struct wl_array key_bindings;
31+
32+    struct wl_listener tty_listener;
33+    struct wl_listener drm_listener;
34+
35+    struct wl_signal destroy_signal;
36+};
37+
38+bool swc_compositor_initialize(struct swc_compositor * compositor,
39+                               struct wl_display * display);
40+
41+void swc_compositor_finish(struct swc_compositor * compositor);
42+
43+void swc_compositor_add_globals(struct swc_compositor * compositor,
44+                                struct wl_display * display);
45+
46+void swc_compositor_add_key_binding(struct swc_compositor * compositor,
47+                                    uint32_t modifiers, xkb_keysym_t key,
48+                                    swc_binding_handler_t handler, void * data);
49+
50+#endif
51+
+37, -0
 1@@ -0,0 +1,37 @@
 2+dnl swc: configure.ac
 3+
 4+AC_PREREQ([2.59])
 5+
 6+AC_INIT([swc], [0.0.1], [mforney@mforney.org])
 7+AM_INIT_AUTOMAKE([foreign -Wall -Werror])
 8+AC_LANG([C])
 9+
10+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
11+
12+AC_PROG_CC_C99
13+AC_USE_SYSTEM_EXTENSIONS
14+
15+AM_PROG_AR
16+LT_INIT
17+
18+AC_CONFIG_SRCDIR([compositor.c])
19+AC_CONFIG_MACRO_DIR([m4])
20+
21+PKG_PROG_PKG_CONFIG([0.9.0])
22+
23+dnl Check for libraries {{{
24+PKG_CHECK_MODULES([wayland_server], [wayland-server])
25+PKG_CHECK_MODULES([udev], [libudev])
26+PKG_CHECK_MODULES([xkbcommon], [xkbcommon])
27+PKG_CHECK_MODULES([drm], [libdrm])
28+PKG_CHECK_MODULES([gbm], [gbm])
29+PKG_CHECK_MODULES([egl], [egl])
30+PKG_CHECK_MODULES([pixman], [pixman-1])
31+
32+PKG_CHECK_MODULES([wayland_client], [wayland-client])
33+dnl }}}
34+
35+#AC_CONFIG_HEADERS([config.h])
36+AC_CONFIG_FILES([Makefile i915/Makefile testwm/Makefile])
37+AC_OUTPUT
38+
A drm.c
+355, -0
  1@@ -0,0 +1,355 @@
  2+#include <stdio.h>
  3+#include <stdlib.h>
  4+#include <string.h>
  5+#include <fcntl.h>
  6+#include <unistd.h>
  7+#include <libudev.h>
  8+#include <libdrm/drm.h>
  9+#include <xf86drm.h>
 10+#include <libdrm/i915_drm.h>
 11+//#include <xf86drmMode.h>
 12+#include <wayland-util.h>
 13+
 14+#include "drm.h"
 15+#include "output.h"
 16+#include "event.h"
 17+
 18+static struct udev_device * find_primary_drm_device(struct udev * udev,
 19+                                                    const char * seat)
 20+{
 21+    struct udev_enumerate * enumerate;
 22+    struct udev_list_entry * entry;
 23+    const char * path;
 24+    const char * device_seat;
 25+    const char * boot_vga;
 26+    struct udev_device * pci;
 27+    struct udev_device * device, * drm_device = NULL;
 28+
 29+    enumerate = udev_enumerate_new(udev);
 30+    udev_enumerate_add_match_subsystem(enumerate, "drm");
 31+    udev_enumerate_add_match_sysname(enumerate, "card[0-9]*");
 32+
 33+    udev_enumerate_scan_devices(enumerate);
 34+
 35+    udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(enumerate))
 36+    {
 37+        path = udev_list_entry_get_name(entry);
 38+        device = udev_device_new_from_syspath(udev, path);
 39+
 40+        printf("device node path: %s\n", udev_device_get_devnode(device));
 41+
 42+        device_seat = udev_device_get_property_value(device, "ID_SEAT");
 43+
 44+        /* If the ID_SEAT property is not set, the device belongs to seat0. */
 45+        if (!device_seat)
 46+            device_seat = "seat0";
 47+        else
 48+            printf("device seat: %s\n", device_seat);
 49+
 50+        /* Make sure the DRM device belongs to the seat we are in. */
 51+        if (strcmp(device_seat, seat) != 0)
 52+        {
 53+            udev_device_unref(device);
 54+            continue;
 55+        }
 56+
 57+        pci = udev_device_get_parent_with_subsystem_devtype(device, "pci",
 58+                                                            NULL);
 59+
 60+        if (pci)
 61+        {
 62+            /* boot_vga = 1 indicates that this DRM device is the primary GPU. */
 63+            boot_vga = udev_device_get_sysattr_value(pci, "boot_vga");
 64+            if (boot_vga && strcmp(boot_vga, "1") == 0)
 65+            {
 66+                if (drm_device)
 67+                    udev_device_unref(drm_device);
 68+                drm_device = device;
 69+                break;
 70+            }
 71+        }
 72+
 73+        /* Make sure we have a backup device. */
 74+        if (!drm_device)
 75+            drm_device = device;
 76+        else
 77+            udev_device_unref(device);
 78+    }
 79+
 80+    udev_enumerate_unref(enumerate);
 81+
 82+    return drm_device;
 83+}
 84+
 85+static bool find_available_crtc(struct swc_drm * drm, drmModeRes * resources,
 86+                                drmModeConnector * connector,
 87+                                uint32_t taken_crtcs, uint32_t * crtc)
 88+{
 89+    uint32_t encoder_index, crtc_index;
 90+    uint32_t possible_crtcs;
 91+    drmModeEncoder * encoder;
 92+
 93+    for (encoder_index = 0;
 94+         encoder_index < connector->count_encoders;
 95+         ++encoder_index)
 96+    {
 97+        encoder = drmModeGetEncoder(drm->fd, connector->encoders[encoder_index]);
 98+        possible_crtcs = encoder->possible_crtcs;
 99+        drmModeFreeEncoder(encoder);
100+
101+        printf("possible_crtcs: %u\n", possible_crtcs);
102+        printf("taken_crtcs: %u\n", taken_crtcs);
103+
104+        for (crtc_index = 0; crtc_index < resources->count_crtcs; ++crtc_index)
105+        {
106+            if ((possible_crtcs & (1 << crtc_index))
107+                && !(taken_crtcs & (1 << crtc_index)))
108+            {
109+                *crtc = crtc_index;
110+                return true;
111+            }
112+        }
113+    }
114+
115+    return false;
116+}
117+
118+static bool find_available_id(struct swc_drm * drm, uint32_t * id)
119+{
120+    uint32_t index = __builtin_ffsl(~drm->taken_output_ids);
121+
122+    printf("drm->taken_output_ids: %u, index: %u\n", drm->taken_output_ids, index);
123+
124+    if (index == 0)
125+        return false;
126+
127+    *id = index - 1;
128+    return true;
129+}
130+
131+static void handle_vblank(int fd, unsigned int sequence, unsigned int sec,
132+                          unsigned int usec, void * data)
133+{
134+    printf("vblank\n");
135+}
136+
137+static void handle_page_flip(int fd, unsigned int sequence, unsigned int sec,
138+                             unsigned int usec, void * data)
139+{
140+    struct swc_output * output = data;
141+    struct swc_event event = {
142+        .type = SWC_DRM_PAGE_FLIP,
143+        .data = output
144+    };
145+
146+    printf("page flip\n");
147+    output->front_buffer ^= 1;
148+
149+    wl_signal_emit(&output->drm->event_signal, &event);
150+}
151+
152+static drmEventContext event_context = {
153+    .version = DRM_EVENT_CONTEXT_VERSION,
154+    .vblank_handler = &handle_vblank,
155+    .page_flip_handler = &handle_page_flip
156+};
157+
158+static int handle_data(int fd, uint32_t mask, void * data)
159+{
160+    drmHandleEvent(fd, &event_context);
161+
162+    return 1;
163+}
164+
165+bool swc_drm_initialize(struct swc_drm * drm, struct udev * udev,
166+                        const char * seat)
167+{
168+    const char * sysnum;
169+    const char * device_path;
170+    char * end;
171+
172+    wl_signal_init(&drm->event_signal);
173+
174+    struct udev_device * drm_device = find_primary_drm_device(udev, seat);
175+
176+    if (!drm_device)
177+    {
178+        printf("couldn't find drm device\n");
179+        goto error_base;
180+    }
181+
182+    /* XXX: Why do we need the sysnum? */
183+    sysnum = udev_device_get_sysnum(drm_device);
184+    drm->id = strtoul(sysnum, &end, 10);
185+
186+    drm->taken_output_ids = 0;
187+
188+    if (*end != '\0')
189+    {
190+        printf("couldn't get drm device sysnum\n");
191+        goto error_device;
192+    }
193+
194+    printf("sysnum: %s\n", sysnum);
195+
196+    device_path = udev_device_get_devnode(drm_device);
197+    drm->fd = open(device_path, O_RDWR | O_CLOEXEC);
198+
199+    if (drm->fd == -1)
200+    {
201+        printf("couldn't open %s\n", device_path);
202+        goto error_device;
203+    }
204+
205+    {
206+        int value, ret;
207+        struct drm_i915_getparam getparam = {
208+            .param = I915_PARAM_HAS_BLT,
209+            .value = &value
210+        };
211+
212+        ret = drmIoctl(drm->fd, DRM_IOCTL_I915_GETPARAM, &getparam);
213+
214+        printf("has blt: %u\n", ret);
215+    }
216+
217+    udev_device_unref(drm_device);
218+
219+    return true;
220+
221+  error_device:
222+    udev_device_unref(drm_device);
223+  error_base:
224+    return false;
225+}
226+
227+void swc_drm_finish(struct swc_drm * drm)
228+{
229+    close(drm->fd);
230+}
231+
232+void swc_drm_add_event_sources(struct swc_drm * drm,
233+                               struct wl_event_loop * event_loop)
234+{
235+    drm->source = wl_event_loop_add_fd(event_loop, drm->fd, WL_EVENT_READABLE,
236+                                       &handle_data, NULL);
237+}
238+
239+void swc_drm_set_master(struct swc_drm * drm)
240+{
241+    printf("setting drm master\n");
242+    drmSetMaster(drm->fd);
243+}
244+
245+void swc_drm_drop_master(struct swc_drm * drm)
246+{
247+    printf("dropping drm master\n");
248+    drmDropMaster(drm->fd);
249+}
250+
251+struct wl_list * swc_drm_create_outputs(struct swc_drm * drm)
252+{
253+    drmModeRes * resources;
254+    drmModeConnector * connector;
255+    drmModeCrtc * crtc;
256+    uint32_t index;
257+    uint32_t x = 0, y = 0;
258+    struct swc_output * output;
259+    struct wl_list * outputs;
260+    uint32_t taken_crtcs = 0;
261+
262+    outputs = malloc(sizeof(struct wl_list));
263+    wl_list_init(outputs);
264+
265+    resources = drmModeGetResources(drm->fd);
266+    if (!resources)
267+    {
268+        printf("couldn't get DRM resources\n");
269+        goto error;
270+    }
271+
272+    printf("crtc count: %u\n", resources->count_crtcs);
273+
274+    /* XXX: crtcs */
275+    for (index = 0; index < resources->count_crtcs; ++index)
276+    {
277+        printf("crtc[%u]: %u\n", index, resources->crtcs[index]);
278+        drmModeCrtc * crtc = drmModeGetCrtc(drm->fd, resources->crtcs[index]);
279+        printf("crtc, id: %u, x: %u, y: %u, width: %u, height: %u\n",
280+            crtc->crtc_id, crtc->x, crtc->y, crtc->width, crtc->height);
281+        drmModeFreeCrtc(crtc);
282+    }
283+
284+    for (index = 0; index < resources->count_encoders; ++index)
285+    {
286+        printf("encoder[%u]: %u\n", index, resources->encoders[index]);
287+        drmModeEncoder * encoder = drmModeGetEncoder(drm->fd, resources->encoders[index]);
288+        printf("encoder, id: %u, type: %u\n", encoder->encoder_id, encoder->encoder_type);
289+        drmModeFreeEncoder(encoder);
290+    }
291+
292+    for (index = 0; index < resources->count_connectors; ++index)
293+    {
294+        connector = drmModeGetConnector(drm->fd, resources->connectors[index]);
295+
296+        printf("connector, id: %u, type: %u, type_id: %u, connection: %u\n",
297+            connector->connector_id, connector->connector_type,
298+            connector->connector_type_id, connector->connection);
299+
300+        /* XXX: connector id? */
301+        if (connector->connection == DRM_MODE_CONNECTED)
302+        {
303+            uint32_t crtc_index;
304+            uint32_t id;
305+
306+            if (!find_available_crtc(drm, resources, connector, taken_crtcs,
307+                                     &crtc_index))
308+            {
309+                printf("couldn't find crtc for connector %u\n", index);
310+                continue;
311+            }
312+
313+            if (!find_available_id(drm, &id))
314+            {
315+                printf("no more available output IDs\n");
316+                break;
317+            }
318+
319+            output = malloc(sizeof(struct swc_output));
320+
321+            if (!swc_output_initialize(output, drm, id,
322+                                       resources->crtcs[crtc_index], connector))
323+            {
324+                drmModeFreeConnector(connector);
325+                free(output);
326+                continue;
327+            }
328+
329+            output->x = x;
330+            output->y = 0;
331+
332+            taken_crtcs |= 1 << crtc_index;
333+            drm->taken_output_ids |= 1 << id;
334+
335+            wl_list_insert(outputs, &output->link);
336+            x += output->width;
337+        }
338+
339+        drmModeFreeConnector(connector);
340+    }
341+
342+    drmModeFreeResources(resources);
343+
344+    if (wl_list_empty(outputs))
345+    {
346+        printf("couldn't find any outputs\n");
347+        goto error;
348+    }
349+
350+    return outputs;
351+
352+  error:
353+    free(outputs);
354+    return NULL;
355+}
356+
A drm.h
+42, -0
 1@@ -0,0 +1,42 @@
 2+#ifndef SWC_DRM_H
 3+#define SWC_DRM_H 1
 4+
 5+#include <stdbool.h>
 6+#include <stdint.h>
 7+#include <libudev.h>
 8+#include <gbm.h>
 9+#include <wayland-server.h>
10+
11+enum swc_drm_event
12+{
13+    SWC_DRM_PAGE_FLIP
14+};
15+
16+struct swc_drm
17+{
18+    int fd;
19+    uint32_t id;
20+
21+    uint32_t taken_output_ids;
22+
23+    struct wl_event_source * source;
24+
25+    struct wl_signal event_signal;
26+};
27+
28+bool swc_drm_initialize(struct swc_drm * drm, struct udev * udev,
29+                        const char * seat);
30+
31+void swc_drm_finish(struct swc_drm * drm);
32+
33+void swc_drm_add_event_sources(struct swc_drm * drm,
34+                               struct wl_event_loop * event_loop);
35+
36+void swc_drm_set_master(struct swc_drm * drm);
37+
38+void swc_drm_drop_master(struct swc_drm * drm);
39+
40+struct wl_list * swc_drm_create_outputs(struct swc_drm * drm);
41+
42+#endif
43+
A egl.c
+86, -0
 1@@ -0,0 +1,86 @@
 2+#include "egl.h"
 3+
 4+#include <stdio.h>
 5+#include <string.h>
 6+
 7+#define EGL_EGLEXT_PROTOTYPES
 8+#include <EGL/eglext.h>
 9+#undef EGL_EGLEXT_PROTOTYPES
10+
11+bool swc_egl_initialize(struct swc_egl * egl, struct gbm_device * gbm)
12+{
13+    const char * extensions;
14+
15+    egl->display = eglGetDisplay(gbm);
16+
17+    if (egl->display == NULL)
18+    {
19+        printf("could not create egl display\n");
20+        goto error_base;
21+    }
22+
23+    if (!eglInitialize(egl->display, NULL, NULL))
24+    {
25+        printf("could not initialize egl display\n");
26+        goto error_base;
27+    }
28+
29+#if EGL_WL_bind_wayland_display
30+    extensions = eglQueryString(egl->display, EGL_EXTENSIONS);
31+
32+    if (!extensions)
33+    {
34+        printf("could not query EGL extensions\n");
35+        goto error_display;
36+    }
37+
38+    if (strstr(extensions, "EGL_WL_bind_wayland_display"))
39+        egl->has_bind_wayland_display = true;
40+    else
41+    {
42+        printf("warning: headers claim EGL_WL_bind_wayland_display exists, "
43+               "but it is not in the queried extension list\n");
44+        egl->has_bind_wayland_display = false;
45+    }
46+#else
47+    printf("don't have EGL_WL_bind_wayland_display extension\n");
48+    egl->has_bind_wayland_display = false;
49+#endif
50+
51+    return true;
52+
53+  error_display:
54+    eglTerminate(egl->display);
55+    eglReleaseThread();
56+  error_base:
57+    return false;
58+}
59+
60+void swc_egl_finish(struct swc_egl * egl)
61+{
62+    eglTerminate(egl->display);
63+    eglReleaseThread();
64+}
65+
66+bool swc_egl_bind_display(struct swc_egl * egl, struct wl_display * display)
67+{
68+#if EGL_WL_bind_wayland_display
69+    if (egl->has_bind_wayland_display)
70+        return eglBindWaylandDisplayWL(egl->display, display);
71+#endif
72+
73+    /* If we don't have this extension, just continue normally. */
74+    return true;
75+}
76+
77+bool swc_egl_unbind_display(struct swc_egl * egl, struct wl_display * display)
78+{
79+#if EGL_WL_bind_wayland_display
80+    if (egl->has_bind_wayland_display)
81+        return eglUnbindWaylandDisplayWL(egl->display, display);
82+#endif
83+
84+    /* If we don't have this extension, just continue normally. */
85+    return true;
86+}
87+
A egl.h
+25, -0
 1@@ -0,0 +1,25 @@
 2+#ifndef SWC_EGL_H
 3+#define SWC_EGL_H 1
 4+
 5+#include <stdlib.h>
 6+#include <stdbool.h>
 7+#include <wayland-server.h>
 8+#include <gbm.h>
 9+#include <EGL/egl.h>
10+
11+struct swc_egl
12+{
13+    EGLDisplay display;
14+    bool has_bind_wayland_display;
15+};
16+
17+bool swc_egl_initialize(struct swc_egl * egl, struct gbm_device * gbm);
18+
19+void swc_egl_finish(struct swc_egl * egl);
20+
21+bool swc_egl_bind_display(struct swc_egl * egl, struct wl_display * display);
22+
23+bool swc_egl_unbind_display(struct swc_egl * egl, struct wl_display * display);
24+
25+#endif
26+
+220, -0
  1@@ -0,0 +1,220 @@
  2+#include "evdev_device.h"
  3+
  4+#include "seat.h"
  5+
  6+#include <stdlib.h>
  7+#include <stdio.h>
  8+#include <string.h>
  9+#include <fcntl.h>
 10+#include <unistd.h>
 11+
 12+#define BITS(var, n) uint64_t var[((n)-1)/64+1]
 13+#define TEST_BIT(var, n) \
 14+    (((var)[(n)/((sizeof (var)[0])*8)] >> ((n)%((sizeof (var)[0])*8))) & 1)
 15+
 16+static inline uint32_t timeval_to_msec(struct timeval * time)
 17+{
 18+    return time->tv_sec * 1000 + time->tv_usec / 1000;
 19+}
 20+
 21+static void handle_key_event(struct swc_evdev_device * device,
 22+                             struct input_event * event)
 23+{
 24+    uint32_t time = timeval_to_msec(&event->time);
 25+
 26+    if ((event->code >= BTN_MISC && event->code <= BTN_GEAR_UP)
 27+        || event->code >= BTN_TRIGGER_HAPPY)
 28+    {
 29+        swc_seat_handle_button(device->seat, time, event->value,
 30+                               event->value ? WL_POINTER_BUTTON_STATE_PRESSED
 31+                                            : WL_POINTER_BUTTON_STATE_RELEASED);
 32+    }
 33+    else
 34+    {
 35+        swc_seat_handle_key(device->seat, time, event->code,
 36+                            event->value ? WL_KEYBOARD_KEY_STATE_PRESSED
 37+                                         : WL_KEYBOARD_KEY_STATE_RELEASED);
 38+    }
 39+}
 40+
 41+static void handle_rel_event(struct swc_evdev_device * device,
 42+                             struct input_event * event)
 43+{
 44+    //printf("rel event\n");
 45+
 46+    switch (event->code)
 47+    {
 48+        case REL_X:
 49+            //printf("rel_x: %d\n", event->value);
 50+            break;
 51+        case REL_Y:
 52+            //printf("rel_y: %d\n", event->value);
 53+            break;
 54+    }
 55+}
 56+
 57+static void handle_abs_event(struct swc_evdev_device * device,
 58+                             struct input_event * event)
 59+{
 60+    printf("abs event\n");
 61+}
 62+
 63+static void (* event_handlers[])(struct swc_evdev_device * device,
 64+                                 struct input_event * event) = {
 65+    [EV_KEY] = &handle_key_event,
 66+    [EV_REL] = &handle_rel_event,
 67+    [EV_ABS] = &handle_abs_event
 68+};
 69+
 70+static bool is_motion_event(struct input_event * event)
 71+{
 72+    return (event->type == EV_REL && (event->code == REL_X || event->code == REL_Y))
 73+        || (event->type == EV_ABS && (event->code == ABS_X || event->code == ABS_Y));
 74+}
 75+
 76+static void handle_motion_events(struct swc_evdev_device * device,
 77+                                 uint32_t time)
 78+{
 79+}
 80+
 81+static void process_events(struct swc_evdev_device * device,
 82+                           struct input_event * events, uint32_t event_count)
 83+{
 84+    struct input_event * event, * end = events + event_count;
 85+
 86+    for (event = events; event != end; ++event)
 87+    {
 88+        if (!is_motion_event(event))
 89+            handle_motion_events(device, timeval_to_msec(&event->time));
 90+
 91+        /*
 92+        printf("processing event, type: %u, code: %u, value: %d\n",
 93+               event->type, event->code, event->value);
 94+        */
 95+
 96+        if (event->type < (sizeof event_handlers / sizeof event_handlers[0])
 97+            && event_handlers[event->type])
 98+        {
 99+            event_handlers[event->type](device, event);
100+        }
101+    }
102+}
103+
104+static int handle_data(int fd, uint32_t mask, void * data)
105+{
106+    struct swc_evdev_device * device = data;
107+    struct input_event events[32];
108+    ssize_t bytes_read;
109+
110+    do
111+    {
112+        bytes_read = read(fd, events, sizeof events);
113+
114+        /* Stop on error */
115+        if (bytes_read == -1)
116+            return 1;
117+
118+        process_events(device, events, bytes_read / sizeof events[0]);
119+    } while (bytes_read > 0);
120+
121+    return 1;
122+}
123+
124+bool swc_evdev_device_initialize(struct swc_evdev_device * device,
125+                                 struct swc_seat * seat,
126+                                 struct udev_device * udev_device)
127+{
128+    const char * path, * model, * vendor;
129+    BITS(ev_bits, EV_MAX);
130+    uint32_t index;
131+
132+    path = udev_device_get_devnode(udev_device);
133+    model = udev_device_get_property_value(udev_device, "ID_MODEL")
134+        ?: "unknown";
135+    vendor = udev_device_get_property_value(udev_device, "ID_VENDOR")
136+        ?: "unknown";
137+
138+    device->seat = seat;
139+    device->model = strdup(model);
140+    device->vendor = strdup(vendor);
141+    device->fd = open(path, O_RDWR | O_NONBLOCK | O_CLOEXEC);
142+
143+    if (device->fd == -1)
144+    {
145+        printf("couldn't open input device at %s\n", path);
146+        goto error_base;
147+    }
148+
149+    printf("adding device %s %s\n", device->vendor, device->model);
150+
151+    ioctl(device->fd, EVIOCGBIT(0, sizeof ev_bits), &ev_bits);
152+
153+    device->capabilities = 0;
154+    /* Currently, I don't care about touch devices. */
155+
156+    if (udev_device_get_property_value(udev_device, "ID_INPUT_KEYBOARD"))
157+    {
158+        device->capabilities |= WL_SEAT_CAPABILITY_KEYBOARD;
159+        printf("\tthis device is a keyboard\n");
160+    }
161+
162+    if (udev_device_get_property_value(udev_device, "ID_INPUT_MOUSE")
163+        || udev_device_get_property_value(udev_device, "ID_INPUT_TOUCHPAD"))
164+    {
165+        device->capabilities |= WL_SEAT_CAPABILITY_POINTER;
166+        printf("\tthis device is a pointer\n");
167+    }
168+
169+    if (device->capabilities & WL_SEAT_CAPABILITY_POINTER)
170+    {
171+        /* Check if the device has relative motion. */
172+        if (TEST_BIT(ev_bits, EV_REL))
173+        {
174+            BITS(rel_bits, REL_MAX);
175+
176+            ioctl(device->fd, EVIOCGBIT(EV_REL, sizeof rel_bits), &rel_bits);
177+
178+            if (TEST_BIT(rel_bits, REL_X) || TEST_BIT(rel_bits, REL_Y))
179+            {
180+            }
181+        }
182+
183+        /* Check if the device has absolute motion. */
184+        if (TEST_BIT(ev_bits, EV_ABS))
185+        {
186+            BITS(abs_bits, ABS_MAX);
187+
188+            ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof abs_bits), &abs_bits);
189+
190+            if (TEST_BIT(abs_bits, ABS_X))
191+                ioctl(device->fd, EVIOCGABS(ABS_X), &device->abs.info.x);
192+            if (TEST_BIT(abs_bits, ABS_Y))
193+                ioctl(device->fd, EVIOCGABS(ABS_X), &device->abs.info.y);
194+        }
195+    }
196+
197+    return true;
198+
199+  error_fd:
200+    close(device->fd);
201+  error_base:
202+    return false;
203+}
204+
205+void swc_evdev_device_finish(struct swc_evdev_device * device)
206+{
207+    wl_event_source_remove(device->source);
208+    free(device->model);
209+    free(device->vendor);
210+    close(device->fd);
211+}
212+
213+void swc_evdev_device_add_event_sources(struct swc_evdev_device * device,
214+                                        struct wl_event_loop * event_loop)
215+{
216+    printf("adding event source for %s %s\n", device->vendor, device->model);
217+    device->source
218+        = wl_event_loop_add_fd(event_loop, device->fd, WL_EVENT_READABLE,
219+                               handle_data, device);
220+}
221+
+48, -0
 1@@ -0,0 +1,48 @@
 2+#ifndef SWC_EVDEV_DEVICE_H
 3+#define SWC_EVDEV_DEVICE_H 1
 4+
 5+#include <stdbool.h>
 6+#include <libudev.h>
 7+#include <linux/input.h>
 8+#include <wayland-server.h>
 9+
10+struct swc_evdev_device
11+{
12+    struct swc_seat * seat;
13+
14+    int fd;
15+    char * model, * vendor;
16+
17+    struct
18+    {
19+        struct
20+        {
21+            struct input_absinfo x, y;
22+        } info;
23+
24+        int32_t x, y;
25+        bool pending;
26+    } abs;
27+
28+    struct
29+    {
30+        bool pending;
31+    } rel;
32+
33+    uint32_t capabilities;
34+
35+    struct wl_event_source * source;
36+    struct wl_list link;
37+};
38+
39+bool swc_evdev_device_initialize(struct swc_evdev_device * device,
40+                                 struct swc_seat * seat,
41+                                 struct udev_device * udev_device);
42+
43+void swc_evdev_device_finish(struct swc_evdev_device * device);
44+
45+void swc_evdev_device_add_event_sources(struct swc_evdev_device * device,
46+                                        struct wl_event_loop * event_loop);
47+
48+#endif
49+
+11, -0
 1@@ -0,0 +1,11 @@
 2+#ifndef SWC_EVENT_H
 3+#define SWC_EVENT_H
 4+
 5+struct swc_event
 6+{
 7+    uint32_t type;
 8+    void * data;
 9+};
10+
11+#endif
12+
+14, -0
 1@@ -0,0 +1,14 @@
 2+# i915/Makefile.am
 3+
 4+AM_CFLAGS = $(drm_CFLAGS)
 5+
 6+noinst_LTLIBRARIES = libi915.la
 7+
 8+libi915_la_SOURCES = \
 9+	bo.c bo.h \
10+	batch.c batch.h \
11+	blt.h \
12+	mi.h
13+
14+libi915_la_LIBADD = $(drm_LIBS)
15+
+134, -0
  1@@ -0,0 +1,134 @@
  2+#include "batch.h"
  3+#include "bo.h"
  4+#include "mi.h"
  5+
  6+#include <stdio.h>
  7+#include <xf86drm.h>
  8+
  9+void i915_batch_initialize(struct i915_batch * batch, int drm)
 10+{
 11+    batch->relocation_count = 0;
 12+    batch->exec_object_count = 0;
 13+    batch->command_count = 0;
 14+    batch->drm = drm;
 15+}
 16+
 17+void i915_batch_flush(struct i915_batch * batch)
 18+{
 19+    struct i915_bo bo;
 20+    uint32_t index = batch->exec_object_count++;
 21+
 22+    mi_batch_buffer_end(batch);
 23+
 24+    /* Pad the batch buffer to the next quad-word. */
 25+    if (batch->command_count & 1)
 26+        mi_noop(batch, false, 0);
 27+
 28+    printf("command count: %u\n", batch->command_count);
 29+
 30+    i915_bo_initialize(batch->drm, &bo, batch->command_count << 2);
 31+    i915_bo_write(batch->drm, &bo, 0, batch->commands, batch->command_count << 2);
 32+
 33+    printf("adding exec object with handle: %u\n", bo.handle);
 34+
 35+    /* Add command buffer */
 36+    batch->exec_objects[index] = (struct drm_i915_gem_exec_object2) {
 37+        .handle = bo.handle,
 38+        .relocation_count = batch->relocation_count,
 39+        .relocs_ptr = (uint64_t) batch->relocations
 40+    };
 41+
 42+    {
 43+        int ret;
 44+        struct drm_i915_gem_execbuffer2 execbuffer_arg = {
 45+            .buffers_ptr = (uint64_t) batch->exec_objects,
 46+            .buffer_count = batch->exec_object_count,
 47+            .batch_start_offset = 0, /* XXX: ? */
 48+            .batch_len = batch->command_count << 2,
 49+            .flags = I915_EXEC_RENDER
 50+        };
 51+
 52+        if ((ret = drmIoctl(batch->drm, DRM_IOCTL_I915_GEM_EXECBUFFER2,
 53+                     &execbuffer_arg)) != 0)
 54+        {
 55+            printf("execbuffer failed: %u\n", -ret);
 56+        }
 57+    }
 58+
 59+    i915_bo_finalize(batch->drm, &bo);
 60+
 61+    /* Set offsets for all our execution objects (except the last one, our
 62+     * command object). */
 63+    for (index = 0; index < batch->exec_object_count - 1; ++index)
 64+        *batch->offsets[index] = batch->exec_objects[index].offset;
 65+
 66+    batch->command_count = 0;
 67+    batch->relocation_count = 0;
 68+    batch->exec_object_count = 0;
 69+}
 70+
 71+#if 0
 72+uint32_t * i915_batch_alloc(struct i915_batch * batch, uint32_t size)
 73+{
 74+    uint32_t * commands;
 75+
 76+    if (i915_batch_space(batch) < size)
 77+        i915_batch_flush(batch);
 78+
 79+    commands = &batch->commands[batch->size];
 80+    batch->command_count += command_count;
 81+
 82+    return commands;
 83+}
 84+#endif
 85+
 86+void i915_batch_ensure_space(struct i915_batch * batch, uint32_t size)
 87+{
 88+    if (i915_batch_space(batch) < size)
 89+        i915_batch_flush(batch);
 90+}
 91+
 92+uint32_t i915_batch_space(struct i915_batch * batch)
 93+{
 94+    /* XXX: reserved space */
 95+    return I915_MAX_COMMANDS - batch->command_count;
 96+}
 97+
 98+uint64_t i915_batch_add_relocation(struct i915_batch * batch,
 99+                                   uint32_t batch_offset, struct i915_bo * bo,
100+                                   uint32_t read_domains, uint32_t write_domain)
101+{
102+    uint32_t index = batch->relocation_count++;
103+
104+    i915_batch_add_exec_object(batch, bo);
105+
106+    printf("offset: %u\n", (batch->command_count + batch_offset) << 2);
107+    printf("current: %u\n", *((uint32_t *)(((void *) batch->commands) + ((batch->command_count + batch_offset) << 2))));
108+
109+    batch->relocations[index] = (struct drm_i915_gem_relocation_entry) {
110+        .target_handle = bo->handle,
111+        /* XXX: delta */
112+        /* XXX: offset */
113+        .offset = (batch->command_count + batch_offset) << 2,
114+        .presumed_offset = bo->last_offset,
115+        .read_domains = read_domains,
116+        .write_domain = write_domain
117+    };
118+
119+    /* Return our offset guess */
120+    return bo->last_offset;
121+}
122+
123+void i915_batch_add_exec_object(struct i915_batch * batch, struct i915_bo * bo)
124+{
125+    uint32_t index = batch->exec_object_count++;
126+
127+    printf("adding exec object with handle: %u\n", bo->handle);
128+
129+    batch->exec_objects[index] = (struct drm_i915_gem_exec_object2) {
130+        .handle = bo->handle
131+    };
132+
133+    batch->offsets[index] = &bo->last_offset;
134+}
135+
+62, -0
 1@@ -0,0 +1,62 @@
 2+#ifndef SWC_I915_BATCH_H
 3+#define SWC_I915_BATCH_H 1
 4+
 5+#include "bo.h"
 6+
 7+#include <stdlib.h>
 8+#include <stdint.h>
 9+#include <stdarg.h>
10+
11+#include <libdrm/i915_drm.h>
12+
13+#define I915_MAX_COMMANDS (1 << 15)
14+#define I915_MAX_RELOCATIONS (1 << 11)
15+#define I915_MAX_EXEC_OBJECTS (1 << 11)
16+
17+struct i915_batch
18+{
19+    int drm;
20+
21+    struct drm_i915_gem_relocation_entry relocations[I915_MAX_RELOCATIONS];
22+    uint64_t * offsets[I915_MAX_RELOCATIONS];
23+    uint32_t relocation_count;
24+
25+    struct drm_i915_gem_exec_object2 exec_objects[I915_MAX_EXEC_OBJECTS];
26+    uint32_t exec_object_count;
27+
28+    //uint32_t header[13];
29+    uint32_t commands[I915_MAX_COMMANDS];
30+    uint32_t command_count;
31+};
32+
33+void i915_batch_initialize(struct i915_batch * batch, int drm);
34+
35+void i915_batch_flush(struct i915_batch * batch);
36+
37+void i915_batch_ensure_space(struct i915_batch * batch, uint32_t size);
38+
39+uint32_t i915_batch_space(struct i915_batch * batch);
40+
41+static inline void i915_batch_add_dword(struct i915_batch * batch,
42+                                        uint32_t dword)
43+{
44+    batch->commands[batch->command_count++] = dword;
45+}
46+
47+static inline void i915_batch_add_dwords(struct i915_batch * batch, uint32_t count, ...)
48+{
49+    va_list dwords;
50+    va_start(dwords, count);
51+    while (count--)
52+        i915_batch_add_dword(batch, va_arg(dwords, int));
53+    va_end(dwords);
54+}
55+
56+uint64_t i915_batch_add_relocation(struct i915_batch * batch,
57+                                   uint32_t batch_offset, struct i915_bo * bo,
58+                                   uint32_t read_domains, uint32_t write_domain);
59+
60+void i915_batch_add_exec_object(struct i915_batch * batch, struct i915_bo * bo);
61+
62+#endif
63+
+180, -0
  1@@ -0,0 +1,180 @@
  2+#ifndef SWC_I915_BLT_H
  3+#define SWC_I915_BLT_H 1
  4+
  5+#include "i915/bo.h"
  6+#include "i915/batch.h"
  7+
  8+#define BR00_CLIENT_2D 0x2
  9+
 10+#define BR00_OPCODE_XY_COLOR_BLT 0x50
 11+#define BR00_OPCODE_XY_SRC_COPY_BLT 0x53
 12+
 13+#define BR00_32BPP_BYTE_MASK_ALPHA (1 << 1)
 14+#define BR00_32BPP_BYTE_MASK_COLOR (1 << 2)
 15+
 16+static inline uint32_t br00(uint8_t client, uint8_t opcode,
 17+                            uint8_t mask_32bpp,
 18+                            bool src_tiling_enable, bool dst_tiling_enable,
 19+                            uint8_t dword_length)
 20+{
 21+    return client           << 29   /* 31:29 */
 22+        | opcode            << 22   /* 28:22 */
 23+        | mask_32bpp        << 20   /* 21:20 */
 24+                                    /* 19:16 */
 25+        | src_tiling_enable << 15   /* 15 */
 26+                                    /* 14:12 */
 27+        | dst_tiling_enable << 11   /* 11 */
 28+                                    /* 10:8 */
 29+        | dword_length      << 0    /* 7:0 */
 30+        ;
 31+}
 32+
 33+static inline uint32_t br09(uint32_t destination_address)
 34+{
 35+                                    /* 31:29 */
 36+    return destination_address << 0 /* 28:0 */
 37+        ;
 38+}
 39+
 40+static inline uint32_t br11(uint16_t source_pitch)
 41+{
 42+                                /* 31:16 */
 43+    return source_pitch << 0    /* 15:0 */
 44+        ;
 45+}
 46+
 47+static inline uint32_t br12(uint32_t source_address)
 48+{
 49+                                /* 31:29 */
 50+    return source_address << 0  /* 28:0 */
 51+        ;
 52+}
 53+
 54+#define BR13_COLOR_DEPTH_8BIT       0x0
 55+#define BR13_COLOR_DEPTH_16BIT_565  0x1
 56+#define BR13_COLOR_DEPTH_16BIT_1555 0x2
 57+#define BR13_COLOR_DEPTH_32BIT      0x3
 58+
 59+/* Commonly used raster operations */
 60+#define BR13_RASTER_OPERATION_SOURCE    0xcc
 61+#define BR13_RASTER_OPERATION_PATTERN   0xf0
 62+
 63+static inline uint32_t br13(bool clipping_enable, uint8_t color_depth,
 64+                            uint8_t raster_operation,
 65+                            uint16_t destination_pitch)
 66+{
 67+                                    /* 31 */
 68+    return clipping_enable  << 30   /* 30 */
 69+                                    /* 29:26 */
 70+        | color_depth       << 24   /* 25:24 */
 71+        | raster_operation  << 16   /* 23:16 */
 72+        | destination_pitch << 0    /* 15:0 */
 73+        ;
 74+}
 75+
 76+static inline uint32_t br16(uint32_t color)
 77+{
 78+    return color << 0 /* 31:0 */
 79+        ;
 80+}
 81+
 82+static inline uint32_t br22(uint16_t destination_y1, uint16_t destination_x1)
 83+{
 84+    return destination_y1   << 16   /* 31:16 */
 85+        | destination_x1    << 0    /* 15:0 */
 86+        ;
 87+}
 88+
 89+static inline uint32_t br23(uint16_t destination_y2, uint16_t destination_x2)
 90+{
 91+    return destination_y2   << 16   /* 31:16 */
 92+        | destination_x2    << 0    /* 15:0 */
 93+        ;
 94+}
 95+
 96+static inline uint32_t br26(uint16_t source_y1, uint16_t source_x1)
 97+{
 98+    return source_y1 << 16  /* 31:16 */
 99+        | source_x1 << 16   /* 15:0 */
100+        ;
101+};
102+
103+static inline void xy_src_copy_blt(struct i915_batch * batch,
104+                                   struct i915_bo * src, uint16_t src_pitch,
105+                                   uint16_t src_x, uint16_t src_y,
106+                                   struct i915_bo * dst, uint16_t dst_pitch,
107+                                   uint16_t dst_x, uint16_t dst_y,
108+                                   uint16_t width, uint16_t height)
109+{
110+#if 0
111+    i915_batch_add_dword(batch, 
112+    uint32_t * commands = i915_batch_alloc(batch, 8);
113+    commands = (uint32_t *)
114+    *commands++ = br00(BR00_CLIENT_2D, BR00_OPCODE_XY_SRC_COPY_BLT,
115+                       BR00_32BPP_BYTE_MASK_ALPHA | BR00_32BPP_BYTE_MASK_COLOR,
116+                       false, false, 6);
117+    *commands++ = br13(false, BR13_COLOR_DEPTH_32BIT,
118+                       BR13_RASTER_OPERATION_SRC,
119+                       dst_pitch);
120+    *commands++ = br22(dst_y, dst_x);
121+    *commands++ = br23(dst_y + height, dst_x + width);
122+    *commands++ = br09(0); /* XXX: dst address */
123+    *commands++ = br26(src_y, src_x);
124+    *commands++ = br11(src_pitch);
125+    *commands++ = br12(0); /* XXX: src address */
126+#endif
127+
128+    uint32_t dst_address, src_address;
129+
130+    i915_batch_ensure_space(batch, 8);
131+
132+    dst_address = i915_batch_add_relocation(batch, 4, dst,
133+                                            I915_GEM_DOMAIN_RENDER,
134+                                            I915_GEM_DOMAIN_RENDER);
135+    src_address = i915_batch_add_relocation(batch, 7, src,
136+                                            I915_GEM_DOMAIN_RENDER, 0);
137+
138+    i915_batch_add_dwords(batch, 8,
139+        br00(BR00_CLIENT_2D, BR00_OPCODE_XY_SRC_COPY_BLT,
140+             BR00_32BPP_BYTE_MASK_ALPHA | BR00_32BPP_BYTE_MASK_COLOR,
141+             false, false, 6),
142+        br13(false, BR13_COLOR_DEPTH_32BIT, BR13_RASTER_OPERATION_SOURCE,
143+             dst_pitch),
144+        br22(dst_y, dst_x),
145+        br23(dst_y + height, dst_x + width),
146+        br09(dst_address),
147+        br26(src_y, src_x),
148+        br11(src_pitch),
149+        br12(src_address)
150+    );
151+}
152+
153+static inline void xy_color_blt(struct i915_batch * batch,
154+                                struct i915_bo * dst, uint16_t dst_pitch,
155+                                uint16_t dst_x, uint16_t dst_y,
156+                                uint16_t width, uint16_t height,
157+                                uint32_t color)
158+{
159+    uint32_t dst_address;
160+
161+    i915_batch_ensure_space(batch, 6);
162+
163+    dst_address = i915_batch_add_relocation(batch, 4, dst,
164+                                            I915_GEM_DOMAIN_RENDER,
165+                                            I915_GEM_DOMAIN_RENDER);
166+
167+    i915_batch_add_dwords(batch, 6,
168+        br00(BR00_CLIENT_2D, BR00_OPCODE_XY_COLOR_BLT,
169+             BR00_32BPP_BYTE_MASK_ALPHA | BR00_32BPP_BYTE_MASK_COLOR,
170+             false, false, 4),
171+        br13(false, BR13_COLOR_DEPTH_32BIT, BR13_RASTER_OPERATION_PATTERN,
172+             dst_pitch),
173+        br22(dst_y, dst_x),
174+        br23(dst_y + height, dst_x + width),
175+        br09(dst_address),
176+        br16(color)
177+    );
178+}
179+
180+#endif
181+
+52, -0
 1@@ -0,0 +1,52 @@
 2+#include "bo.h"
 3+
 4+#include <stdio.h>
 5+#include <xf86drm.h>
 6+#include <libdrm/i915_drm.h>
 7+
 8+bool i915_bo_initialize(int drm, struct i915_bo * bo, uint32_t size)
 9+{
10+    struct drm_i915_gem_create create_arg = { .size = size };
11+
12+    if (drmCommandWriteRead(drm, DRM_I915_GEM_CREATE, &create_arg,
13+                            sizeof create_arg) != 0)
14+    {
15+        printf("could not create bo\n");
16+        goto error_base;
17+    }
18+
19+    bo->handle = create_arg.handle;
20+    bo->size = size;
21+
22+    bo->last_offset = 0;
23+
24+    return true;
25+
26+  error_base:
27+    return false;
28+}
29+
30+void i915_bo_finalize(int drm, struct i915_bo * bo)
31+{
32+    struct drm_gem_close close_arg = { .handle = bo->handle };
33+
34+    drmIoctl(drm, DRM_IOCTL_GEM_CLOSE, &close_arg);
35+}
36+
37+void i915_bo_write(int drm, struct i915_bo * bo, uint32_t offset,
38+                   void * data, size_t size)
39+{
40+    struct drm_i915_gem_pwrite pwrite_arg = {
41+        .handle = bo->handle,
42+        .offset = offset,
43+        .size = size,
44+        .data_ptr = (uint64_t) data
45+    };
46+
47+    if (drmCommandWrite(drm, DRM_I915_GEM_PWRITE, &pwrite_arg,
48+                        sizeof pwrite_arg) != 0)
49+    {
50+        printf("write failed\n");
51+    }
52+}
53+
+24, -0
 1@@ -0,0 +1,24 @@
 2+#ifndef SWC_I915_BO_H
 3+#define SWC_I915_BO_H 1
 4+
 5+#include <stdlib.h>
 6+#include <stdint.h>
 7+#include <stdbool.h>
 8+
 9+struct i915_bo
10+{
11+    uint32_t handle;
12+    uint32_t size;
13+
14+    uint64_t last_offset;
15+};
16+
17+bool i915_bo_initialize(int drm, struct i915_bo * bo, uint32_t size);
18+
19+void i915_bo_finalize(int drm, struct i915_bo * bo);
20+
21+void i915_bo_write(int drm, struct i915_bo * bo, uint32_t offset,
22+                   void * data, size_t size);
23+
24+#endif
25+
+97, -0
 1@@ -0,0 +1,97 @@
 2+#ifndef SWC_I915_MI_H
 3+#define SWC_I915_MI_H 1
 4+
 5+#include "batch.h"
 6+
 7+#include <stdint.h>
 8+#include <stdbool.h>
 9+
10+#define COMMAND_TYPE_MI 0x0
11+
12+#define MI_OPCODE_NOOP                  0x00
13+#define MI_OPCODE_FLUSH                 0x04
14+#define MI_OPCODE_BATCH_BUFFER_END      0x0A
15+#define MI_OPCODE_FLUSH_DW              0x04
16+#define MI_OPCODE_BATCH_BUFFER_START    0x31
17+
18+static inline void mi_noop(struct i915_batch * batch,
19+                           bool identification_number_write_enable,
20+                           uint32_t identification_number)
21+{
22+    i915_batch_add_dword(batch,
23+        COMMAND_TYPE_MI << 29                           /* 31:29 */
24+            | MI_OPCODE_NOOP << 23                      /* 28:23 */
25+            | identification_number_write_enable << 22  /* 22 */
26+            | identification_number << 0                /* 21:0 */
27+    );
28+}
29+
30+static inline void mi_flush(struct i915_batch * batch,
31+                            bool protected_memory_enable,
32+                            bool indirect_state_pointers_disable,
33+                            bool generic_media_state_clear,
34+                            bool global_snapshot_count_reset,
35+                            bool render_cache_flush_inhibit,
36+                            bool state_cache_invalidate)
37+{
38+    i915_batch_add_dword(batch,
39+        COMMAND_TYPE_MI << 29                       /* 31:29 */
40+            | MI_OPCODE_FLUSH << 23                 /* 28:23 */
41+                                                    /* 22:7 */
42+            | protected_memory_enable << 6          /* 6 */
43+            | indirect_state_pointers_disable << 5  /* 5 */
44+            | generic_media_state_clear << 4        /* 4 */
45+            | global_snapshot_count_reset << 3      /* 3 */
46+            | render_cache_flush_inhibit << 2       /* 2 */
47+            | state_cache_invalidate                /* 1 */
48+                                                    /* 0 */
49+    );
50+}
51+
52+static inline void mi_flush_dw(struct i915_batch * batch)
53+{
54+    i915_batch_add_dwords(batch, 4,
55+        COMMAND_TYPE_MI << 29
56+            | MI_OPCODE_FLUSH_DW << 23
57+            | 2
58+            ,
59+        0,
60+        0,
61+        0
62+    );
63+}
64+
65+static inline void mi_batch_buffer_end(struct i915_batch * batch)
66+{
67+    /* XXX: semaphore data dword / semaphore address */
68+    i915_batch_add_dword(batch,
69+        COMMAND_TYPE_MI << 29                   /* 31:29 */
70+            | MI_OPCODE_BATCH_BUFFER_END << 23  /* 28:23 */
71+                                                /* 22:0 */
72+    );
73+}
74+
75+static inline void mi_batch_buffer_start(struct i915_batch * batch,
76+                                         bool encrypted_memory_enable,
77+                                         bool clear_command_buffer_enable,
78+                                         bool buffer_non_secure,
79+                                         uint32_t buffer_address)
80+{
81+    i915_batch_ensure_space(batch, 2);
82+
83+    i915_batch_add_dwords(batch, 2,
84+        COMMAND_TYPE_MI << 29                       /* 31:29 */
85+            | MI_OPCODE_BATCH_BUFFER_START << 23    /* 28:23 */
86+                                                    /* 22:13 */
87+            | encrypted_memory_enable << 12         /* 12 */
88+            | clear_command_buffer_enable << 11     /* 11 */
89+                                                    /* 10:9 */
90+            | buffer_non_secure << 8                /* 8 */
91+            | 0                                     /* 7:0 */
92+            ,
93+        buffer_address
94+    );
95+}
96+
97+#endif
98+
A mode.c
+20, -0
 1@@ -0,0 +1,20 @@
 2+#include <stdio.h>
 3+
 4+#include "mode.h"
 5+
 6+bool swc_mode_initialize(struct swc_mode * mode, drmModeModeInfo * mode_info)
 7+{
 8+    mode->width = mode_info->hdisplay;
 9+    mode->height = mode_info->vdisplay;
10+    mode->refresh = mode_info->vrefresh * 1000;
11+    mode->preferred = mode_info->type & DRM_MODE_TYPE_PREFERRED;
12+
13+    mode->info = *mode_info;
14+
15+    return true;
16+}
17+
18+void swc_mode_finish(struct swc_mode * mode)
19+{
20+}
21+
A mode.h
+25, -0
 1@@ -0,0 +1,25 @@
 2+#ifndef SWC_MODE_H
 3+#define SWC_MODE_H
 4+
 5+#include <stdint.h>
 6+#include <stdbool.h>
 7+#include <xf86drmMode.h>
 8+
 9+#include <wayland-util.h>
10+
11+struct swc_mode
12+{
13+    uint16_t width, height;
14+    uint32_t refresh;
15+
16+    bool preferred;
17+
18+    drmModeModeInfo info;
19+};
20+
21+bool swc_mode_initialize(struct swc_mode * mode, drmModeModeInfo * mode_info);
22+
23+void swc_mode_finish(struct swc_mode * mode);
24+
25+#endif
26+
+196, -0
  1@@ -0,0 +1,196 @@
  2+#include "output.h"
  3+
  4+#include "mode.h"
  5+#include "util.h"
  6+
  7+#include <stdio.h>
  8+#include <stdlib.h>
  9+#include <string.h>
 10+
 11+#include <libdrm/i915_drm.h>
 12+#include <xf86drm.h>
 13+
 14+static void bind_output(struct wl_client * client, void * data,
 15+                        uint32_t version, uint32_t id)
 16+{
 17+    struct swc_output * output = data;
 18+    struct swc_mode * mode;
 19+    struct wl_resource * resource;
 20+    uint32_t flags;
 21+
 22+    resource = wl_client_add_object(client, &wl_output_interface, NULL, id,
 23+                                    output);
 24+    wl_list_insert(&output->resource_list, &resource->link);
 25+    resource->destroy = &swc_unbind_resource;
 26+
 27+    wl_output_send_geometry(resource, output->x, output->y,
 28+        output->physical_width, output->physical_height, 0, "unknown",
 29+        "unknown", WL_OUTPUT_TRANSFORM_NORMAL);
 30+
 31+    wl_array_for_each(mode, &output->modes)
 32+    {
 33+        flags = 0;
 34+        if (mode->preferred)
 35+            flags |= WL_OUTPUT_MODE_PREFERRED;
 36+        if (output->current_mode == mode)
 37+            flags |= WL_OUTPUT_MODE_CURRENT;
 38+
 39+        wl_output_send_mode(resource, flags, mode->width, mode->height,
 40+                            mode->refresh);
 41+    }
 42+}
 43+
 44+bool swc_output_initialize(struct swc_output * output, struct swc_drm * drm,
 45+                           uint32_t id, uint32_t crtc_id,
 46+                           drmModeConnector * connector)
 47+{
 48+    drmModeEncoder * encoder;
 49+    drmModeCrtc * current_crtc;
 50+    struct swc_mode * modes;
 51+    uint32_t index;
 52+
 53+    output->drm = drm;
 54+
 55+    printf("initializing output with id: %u\n", id);
 56+
 57+    output->id = id;
 58+    output->repaint_scheduled = false;
 59+    output->front_buffer = 0;
 60+
 61+    output->physical_width = connector->mmWidth;
 62+    output->physical_height = connector->mmHeight;
 63+
 64+    wl_list_init(&output->resource_list);
 65+    wl_array_init(&output->modes);
 66+
 67+    output->crtc_id = crtc_id;
 68+    output->connector_id = connector->connector_id;
 69+
 70+    /* Determine the current CRTC of this output. */
 71+    encoder = drmModeGetEncoder(drm->fd, connector->encoder_id);
 72+    current_crtc = drmModeGetCrtc(drm->fd, encoder->crtc_id);
 73+    drmModeFreeEncoder(encoder);
 74+
 75+    modes = wl_array_add(&output->modes, connector->count_modes * sizeof *modes);
 76+
 77+    for (index = 0; index < connector->count_modes; ++index)
 78+    {
 79+        swc_mode_initialize(&modes[index], &connector->modes[index]);
 80+
 81+        if (memcmp(&modes[index].info, &current_crtc->mode,
 82+                   sizeof(drmModeModeInfo)) == 0)
 83+            output->current_mode = &modes[index];
 84+        if (modes[index].preferred)
 85+            output->preferred_mode = &modes[index];
 86+    }
 87+
 88+    if (output->preferred_mode)
 89+        output->current_mode = output->preferred_mode;
 90+
 91+    output->width = output->current_mode->width;
 92+    output->height = output->current_mode->height;
 93+
 94+    /* Create output buffers */
 95+    if (!swc_buffer_initialize(&output->buffers[0], drm, output->width,
 96+                               output->height))
 97+    {
 98+        printf("could not initialize buffer 0 for output\n");
 99+        goto error_base;
100+    }
101+
102+    if (!swc_buffer_initialize(&output->buffers[1], drm, output->width,
103+                               output->height))
104+    {
105+        printf("could not initialize buffer 1 for output\n");
106+        goto error_buffer0;
107+    }
108+
109+    {
110+        uint32_t color = 0x00339933;
111+        uint32_t line[output->width];
112+        uint32_t x, y;
113+        struct drm_i915_gem_pwrite arg = {
114+            .handle = output->buffers[0].bo.handle,
115+            .size = sizeof line,
116+            .data_ptr = (uint64_t) line
117+        };
118+
119+        for (x = 0; x < output->width; ++x)
120+            line[x] = color;
121+
122+        for (y = 0; y < output->height; ++y)
123+        {
124+            arg.offset += output->buffers[0].pitch;
125+            drmCommandWrite(drm->fd, DRM_I915_GEM_PWRITE, &arg, sizeof arg);
126+        }
127+
128+        color = 0x00333399;
129+
130+        arg.offset = 0;
131+        arg.handle = output->buffers[1].bo.handle;
132+
133+        for (x = 0; x < output->width; ++x)
134+            line[x] = color;
135+
136+        for (y = 0; y < output->height; ++y)
137+        {
138+            arg.offset += output->buffers[1].pitch;
139+            drmCommandWrite(drm->fd, DRM_I915_GEM_PWRITE, &arg, sizeof arg);
140+        }
141+    }
142+
143+    output->original_state.crtc = current_crtc;
144+
145+    if (drmModeSetCrtc(drm->fd, output->crtc_id, output->buffers[0].id, 0, 0,
146+                       &output->connector_id, 1, &output->current_mode->info) != 0)
147+    {
148+        printf("could not set crtc for output\n");
149+        goto error_buffer1;
150+    }
151+
152+    return true;
153+
154+  error_buffer1:
155+    swc_buffer_finish(&output->buffers[1], drm);
156+  error_buffer0:
157+    swc_buffer_finish(&output->buffers[0], drm);
158+  error_base:
159+    return false;
160+}
161+
162+void swc_output_finish(struct swc_output * output)
163+{
164+    struct swc_mode * mode;
165+    drmModeCrtc * crtc = output->original_state.crtc;
166+
167+    wl_array_for_each(mode, &output->modes)
168+        swc_mode_finish(mode);
169+    wl_array_release(&output->modes);
170+
171+    drmModeSetCrtc(output->drm->fd, crtc->crtc_id, crtc->buffer_id, crtc->x,
172+                   crtc->y, &output->connector_id, 1, &crtc->mode);
173+    drmModeFreeCrtc(crtc);
174+
175+    swc_buffer_finish(&output->buffers[0], output->drm);
176+    swc_buffer_finish(&output->buffers[1], output->drm);
177+}
178+
179+void swc_output_add_globals(struct swc_output * output,
180+                            struct wl_display * display)
181+{
182+    wl_display_add_global(display, &wl_output_interface, output, &bind_output);
183+}
184+
185+void swc_output_switch_buffer(struct swc_output * output)
186+{
187+    printf("queueing pageflip\n");
188+
189+    /* Queue a page flip */
190+    if (drmModePageFlip(output->drm->fd, output->crtc_id,
191+                        swc_output_get_back_buffer(output)->id,
192+                        DRM_MODE_PAGE_FLIP_EVENT, output) != 0)
193+    {
194+        printf("could not queue pageflip\n");
195+    }
196+}
197+
+69, -0
 1@@ -0,0 +1,69 @@
 2+#ifndef SWC_OUTPUT_H
 3+#define SWC_OUTPUT_H 1
 4+
 5+#include "buffer.h"
 6+
 7+#include <stdint.h>
 8+#include <wayland-util.h>
 9+#include <wayland-server.h>
10+#include <xf86drmMode.h>
11+
12+struct swc_output
13+{
14+    /* Outputs need IDs so surfaces can keep track of which output they are
15+     * visible on. */
16+    uint32_t id;
17+
18+    struct swc_drm * drm;
19+
20+    /* The geometry of this output */
21+    uint32_t x, y, width, height;
22+    uint32_t physical_width, physical_height;
23+
24+    struct wl_array modes;
25+    struct swc_mode * current_mode, * preferred_mode;
26+
27+    /* Use double buffering */
28+    struct swc_buffer buffers[2];
29+    uint8_t front_buffer;
30+
31+    /* The CRTC and connector we are using to drive this output */
32+    uint32_t crtc_id;
33+    uint32_t connector_id;
34+
35+    struct
36+    {
37+        drmModeCrtc * crtc;
38+    } original_state;
39+
40+    bool repaint_scheduled;
41+
42+    struct wl_list resource_list;
43+    struct wl_list link;
44+};
45+
46+bool swc_output_initialize(struct swc_output * output, struct swc_drm * drm,
47+                           uint32_t id, uint32_t crtc_id,
48+                           drmModeConnector * connector);
49+
50+void swc_output_finish(struct swc_output * output);
51+
52+void swc_output_add_globals(struct swc_output * output,
53+                            struct wl_display * display);
54+
55+void swc_output_switch_buffer(struct swc_output * output);
56+
57+static inline struct swc_buffer * swc_output_get_front_buffer
58+    (struct swc_output * output)
59+{
60+    return &output->buffers[output->front_buffer];
61+}
62+
63+static inline struct swc_buffer * swc_output_get_back_buffer
64+    (struct swc_output * output)
65+{
66+    return &output->buffers[!output->front_buffer];
67+}
68+
69+#endif
70+
+175, -0
  1@@ -0,0 +1,175 @@
  2+#include "renderer.h"
  3+#include "i915/blt.h"
  4+#include "i915/mi.h"
  5+
  6+#include <stdio.h>
  7+#include <GLES2/gl2.h>
  8+#include <libdrm/intel_bufmgr.h>
  9+
 10+struct wl_drm_buffer
 11+{
 12+    struct wl_buffer buffer;
 13+    struct wl_drm * drm;
 14+    uint32_t format;
 15+    const void * driver_format;
 16+    int32_t offset[3];
 17+    int32_t stride[3];
 18+    void * driver_buffer;
 19+};
 20+
 21+struct __DRIimageRec
 22+{
 23+    struct intel_region * region;
 24+    GLenum internal_format;
 25+    uint32_t dri_format;
 26+    GLuint format;
 27+    uint32_t offset;
 28+    uint32_t strides[3];
 29+    uint32_t offsets[3];
 30+    struct intel_image_format * planar_format;
 31+    void * data;
 32+};
 33+
 34+struct intel_region
 35+{
 36+    drm_intel_bo * bo;
 37+    GLuint refcount;
 38+    GLuint cpp;
 39+    GLuint width;
 40+    GLuint height;
 41+    GLuint pitch;
 42+    GLubyte * map;
 43+    GLuint map_refcount;
 44+    uint32_t tiling;
 45+    uint32_t name;
 46+    struct intel_screen * screen;
 47+};
 48+
 49+static inline uint32_t format_wayland_to_pixman(uint32_t wayland_format)
 50+{
 51+    switch (wayland_format)
 52+    {
 53+        case WL_SHM_FORMAT_XRGB8888:
 54+            return PIXMAN_x8r8g8b8;
 55+        case WL_SHM_FORMAT_ARGB8888:
 56+            return PIXMAN_a8r8g8b8;
 57+    }
 58+
 59+    return 0;
 60+}
 61+
 62+static void repaint_surface_for_output(struct swc_renderer * renderer,
 63+                                       struct swc_surface * surface,
 64+                                       struct swc_output * output)
 65+{
 66+    struct swc_buffer * back_buffer = swc_output_get_back_buffer(output);
 67+
 68+    if (wl_buffer_is_shm(surface->state.buffer))
 69+    {
 70+        printf("repainting shm surface\n");
 71+        pixman_image_composite32(PIXMAN_OP_SRC,
 72+                                 surface->renderer_state.shm.image, NULL,
 73+                                 back_buffer->image,
 74+                                 0, 0, 0, 0, 0, 0,
 75+                                 surface->geometry.width,
 76+                                 surface->geometry.height);
 77+    }
 78+    else
 79+    {
 80+        /*
 81+        struct i915_bo * src = &surface->renderer_state.drm.bo;
 82+        uint32_t src_pitch = surface->renderer_state.drm.pitch;
 83+
 84+        xy_src_copy_blt(&renderer->batch, src, src_pitch, 0, 0,
 85+                        &back_buffer->bo, back_buffer->pitch, 0, 0,
 86+                        surface->geometry.width, surface->geometry.height);
 87+        */
 88+    }
 89+}
 90+
 91+bool swc_renderer_initialize(struct swc_renderer * renderer,
 92+                             struct swc_drm * drm)
 93+{
 94+    renderer->drm = drm;
 95+
 96+    i915_batch_initialize(&renderer->batch, drm->fd);
 97+
 98+    return true;
 99+}
100+
101+void swc_renderer_finalize(struct swc_renderer * renderer)
102+{
103+}
104+
105+void swc_renderer_repaint_output(struct swc_renderer * renderer,
106+                                 struct swc_output * output,
107+                                 struct wl_list * surfaces)
108+{
109+    struct swc_surface * surface;
110+
111+    printf("repainting output %u\n", output->id);
112+
113+    wl_list_for_each(surface, surfaces, link)
114+    {
115+        if (surface->output_mask & (1 << output->id))
116+        {
117+            repaint_surface_for_output(renderer, surface, output);
118+        }
119+    }
120+
121+    xy_color_blt(&renderer->batch, &swc_output_get_back_buffer(output)->bo,
122+                 swc_output_get_back_buffer(output)->pitch, 0, 0, 500, 500,
123+                 0xffffffff);
124+
125+    //mi_flush(&renderer->batch, false, false, false, false, false, false);
126+
127+    i915_batch_flush(&renderer->batch);
128+}
129+
130+void swc_renderer_attach(struct swc_renderer * renderer,
131+                         struct wl_list * outputs,
132+                         struct swc_surface * surface,
133+                         struct wl_buffer * buffer)
134+{
135+    if (wl_buffer_is_shm(buffer))
136+    {
137+        struct swc_output * output;
138+        uint32_t wayland_format = wl_shm_buffer_get_format(buffer);
139+
140+        surface->renderer_state.shm.image
141+            = pixman_image_create_bits(format_wayland_to_pixman(wayland_format),
142+                                       wl_shm_buffer_get_width(buffer),
143+                                       wl_shm_buffer_get_height(buffer),
144+                                       wl_shm_buffer_get_data(buffer),
145+                                       wl_shm_buffer_get_stride(buffer));
146+
147+        wl_list_for_each(output, outputs, link)
148+        {
149+            if (surface->output_mask & (1 << output->id))
150+            {
151+                swc_buffer_ref_image(&output->buffers[0], renderer->drm);
152+                swc_buffer_ref_image(&output->buffers[1], renderer->drm);
153+            }
154+        }
155+    }
156+    else
157+    {
158+        struct wl_drm_buffer * drm_buffer = (void *) surface->state.buffer;
159+        struct __DRIimageRec * image = drm_buffer->driver_buffer;
160+        struct intel_region * region = image->region;
161+        drm_intel_bo * bo = region->bo;
162+
163+        surface->renderer_state.drm.bo = (struct i915_bo) {
164+            .handle = bo->handle
165+        };
166+
167+        surface->renderer_state.drm.pitch = region->pitch;
168+
169+        printf("buffer width: %u, height: %u\n", buffer->width, buffer->height);
170+
171+        printf("bo width: %u, height: %u, stride: %u, handle: %u\n",
172+               region->width, region->height,
173+               region->pitch, bo->handle);
174+    }
175+}
176+
+31, -0
 1@@ -0,0 +1,31 @@
 2+#ifndef SWC_RENDERER_H
 3+#define SWC_RENDERER_H 1
 4+
 5+#include "output.h"
 6+#include "surface.h"
 7+#include "drm.h"
 8+#include "i915/batch.h"
 9+
10+struct swc_renderer
11+{
12+    struct swc_drm * drm;
13+
14+    struct i915_batch batch;
15+};
16+
17+bool swc_renderer_initialize(struct swc_renderer * renderer,
18+                             struct swc_drm * drm);
19+
20+void swc_renderer_finalize(struct swc_renderer * renderer);
21+
22+void swc_renderer_repaint_output(struct swc_renderer * renderer,
23+                                 struct swc_output * output,
24+                                 struct wl_list * surfaces);
25+
26+void swc_renderer_attach(struct swc_renderer * renderer,
27+                         struct wl_list * outputs,
28+                         struct swc_surface * surface,
29+                         struct wl_buffer * buffer);
30+
31+#endif
32+
A seat.c
+294, -0
  1@@ -0,0 +1,294 @@
  2+#include "seat.h"
  3+
  4+#include "evdev_device.h"
  5+#include "util.h"
  6+#include "binding.h"
  7+
  8+#include <stdlib.h>
  9+#include <stdio.h>
 10+#include <string.h>
 11+
 12+struct wl_seat_interface swc_seat_interface = {
 13+    .get_pointer = &swc_seat_get_pointer,
 14+    .get_keyboard = &swc_seat_get_keyboard,
 15+    .get_touch = &swc_seat_get_touch
 16+};
 17+
 18+static void bind_seat(struct wl_client * client, void * data, uint32_t version,
 19+                      uint32_t id)
 20+{
 21+    struct swc_seat * seat = data;
 22+    struct wl_resource * resource;
 23+
 24+    resource = wl_client_add_object(client, &wl_seat_interface,
 25+                                    &swc_seat_interface, id, seat);
 26+    wl_list_insert(&seat->wayland.base_resource_list, &resource->link);
 27+    resource->destroy = &swc_unbind_resource;
 28+
 29+    wl_seat_send_capabilities(resource, seat->capabilities);
 30+}
 31+
 32+static void add_device(struct swc_seat * seat, struct udev_device * udev_device)
 33+{
 34+    const char * device_seat;
 35+    const char * device_path;
 36+    struct swc_evdev_device * evdev_device;
 37+
 38+    device_seat = udev_device_get_property_value(udev_device, "ID_SEAT");
 39+
 40+    /* If the ID_SEAT property is not set, the device belongs to seat0. */
 41+    if (!device_seat)
 42+        device_seat = "seat0";
 43+
 44+    if (strcmp(device_seat, seat->name) != 0)
 45+        return;
 46+
 47+    evdev_device = malloc(sizeof *evdev_device);
 48+
 49+    if (!swc_evdev_device_initialize(evdev_device, seat, udev_device))
 50+    {
 51+        free(evdev_device);
 52+        return;
 53+    }
 54+
 55+    if (!(seat->capabilities & WL_SEAT_CAPABILITY_POINTER)
 56+        && evdev_device->capabilities & WL_SEAT_CAPABILITY_POINTER)
 57+    {
 58+        printf("initializing pointer\n");
 59+        wl_pointer_init(&seat->pointer);
 60+        wl_seat_set_pointer(&seat->wayland, &seat->pointer);
 61+    }
 62+
 63+    if (!(seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
 64+        && evdev_device->capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
 65+    {
 66+        printf("initializing keyboard\n");
 67+        wl_keyboard_init(&seat->keyboard);
 68+        wl_seat_set_keyboard(&seat->wayland, &seat->keyboard);
 69+    }
 70+
 71+    seat->capabilities |= evdev_device->capabilities;
 72+
 73+    wl_list_insert(&seat->devices, &evdev_device->link);
 74+}
 75+
 76+bool swc_seat_initialize(struct swc_seat * seat, struct udev * udev,
 77+                         const char * seat_name)
 78+{
 79+    wl_seat_init(&seat->wayland);
 80+
 81+    seat->name = strdup(seat_name);
 82+    seat->capabilities = 0;
 83+    seat->active_modifiers = 0;
 84+
 85+    if (!swc_xkb_initialize(&seat->xkb))
 86+    {
 87+        printf("could not initialize XKB\n");
 88+        goto error_name;
 89+    }
 90+
 91+    wl_list_init(&seat->devices);
 92+    swc_seat_add_devices(seat, udev);
 93+
 94+    return true;
 95+
 96+  error_name:
 97+    free(seat->name);
 98+  error_base:
 99+    return false;
100+}
101+
102+void swc_seat_finish(struct swc_seat * seat)
103+{
104+    struct swc_evdev_device * device, * tmp;
105+
106+    wl_seat_release(&seat->wayland);
107+    free(seat->name);
108+    swc_xkb_finish(&seat->xkb);
109+
110+    wl_list_for_each_safe(device, tmp, &seat->devices, link)
111+    {
112+        swc_evdev_device_finish(device);
113+        free(device);
114+    }
115+}
116+
117+void swc_seat_add_globals(struct swc_seat * seat, struct wl_display * display)
118+{
119+    wl_display_add_global(display, &wl_seat_interface, seat, &bind_seat);
120+}
121+
122+void swc_seat_add_event_sources(struct swc_seat * seat,
123+                                struct wl_event_loop * event_loop)
124+{
125+    struct swc_evdev_device * device;
126+
127+    wl_list_for_each(device, &seat->devices, link)
128+    {
129+        swc_evdev_device_add_event_sources(device, event_loop);
130+    }
131+}
132+
133+void swc_seat_add_devices(struct swc_seat * seat, struct udev * udev)
134+{
135+    struct udev_enumerate * enumerate;
136+    struct udev_list_entry * entry;
137+    const char * path;
138+    struct udev_device * device;
139+
140+    enumerate = udev_enumerate_new(udev);
141+    udev_enumerate_add_match_subsystem(enumerate, "input");
142+    udev_enumerate_add_match_sysname(enumerate, "event[0-9]*");
143+
144+    udev_enumerate_scan_devices(enumerate);
145+
146+    udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(enumerate))
147+    {
148+        path = udev_list_entry_get_name(entry);
149+        device = udev_device_new_from_syspath(udev, path);
150+        add_device(seat, device);
151+        udev_device_unref(device);
152+    }
153+
154+    udev_enumerate_unref(enumerate);
155+}
156+
157+void swc_seat_handle_key(struct swc_seat * seat, uint32_t time, uint32_t key,
158+                         uint32_t state)
159+{
160+    uint32_t * pressed_key;
161+    struct wl_keyboard * keyboard = &seat->keyboard;
162+    struct swc_xkb * xkb = &seat->xkb;
163+    enum xkb_key_direction direction;
164+
165+    /* Update XKB state */
166+    direction = state == WL_KEYBOARD_KEY_STATE_PRESSED ? XKB_KEY_DOWN
167+                                                       : XKB_KEY_UP;
168+
169+    /* Apparently these are offset by 8 in X. */
170+    xkb_state_update_key(xkb->state, key + 8, direction);
171+
172+    if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
173+    {
174+        keyboard->grab_key = key;
175+        keyboard->grab_time = time;
176+        pressed_key = wl_array_add(&keyboard->keys, sizeof key);
177+        *pressed_key = key;
178+    }
179+    else
180+    {
181+        wl_array_for_each(pressed_key, &keyboard->keys)
182+        {
183+            if (*pressed_key == key)
184+            {
185+                /* Remove the key from the array */
186+                uint32_t bytes_to_copy = keyboard->keys.size + 1
187+                    - (((void *) pressed_key) - keyboard->keys.data);
188+                memmove(pressed_key, pressed_key + 1, bytes_to_copy);
189+                --keyboard->keys.size;
190+                break;
191+            }
192+        }
193+    }
194+
195+    keyboard->grab->interface->key(keyboard->grab, time, key, state);
196+
197+    {
198+        struct wl_keyboard * keyboard = &seat->keyboard;
199+        uint32_t mods_depressed, mods_latched, mods_locked, mods_active;
200+        uint32_t layout;
201+
202+        mods_depressed = xkb_state_serialize_mods(xkb->state, XKB_STATE_DEPRESSED);
203+        mods_latched = xkb_state_serialize_mods(xkb->state, XKB_STATE_LATCHED);
204+        mods_locked = xkb_state_serialize_mods(xkb->state, XKB_STATE_LOCKED);
205+        mods_active = mods_depressed | mods_latched;
206+
207+        layout = xkb_state_serialize_layout(xkb->state, XKB_STATE_LAYOUT_EFFECTIVE);
208+
209+        if (mods_depressed != keyboard->modifiers.mods_depressed
210+            || mods_latched != keyboard->modifiers.mods_latched
211+            || mods_locked != keyboard->modifiers.mods_locked
212+            || layout != keyboard->modifiers.group)
213+        {
214+        }
215+
216+        keyboard->modifiers.mods_depressed = mods_depressed;
217+        keyboard->modifiers.mods_latched = mods_latched;
218+        keyboard->modifiers.mods_locked = mods_locked;
219+        keyboard->modifiers.group = layout;
220+
221+        seat->active_modifiers = 0;
222+
223+        if (mods_active & (1 << xkb->indices.ctrl))
224+            seat->active_modifiers |= MOD_CTRL;
225+        if (mods_active & (1 << xkb->indices.alt))
226+            seat->active_modifiers |= MOD_ALT;
227+        if (mods_active & (1 << xkb->indices.super))
228+            seat->active_modifiers |= MOD_SUPER;
229+        if (mods_active & (1 << xkb->indices.shift))
230+            seat->active_modifiers |= MOD_SHIFT;
231+    }
232+}
233+
234+void swc_seat_handle_button(struct swc_seat * seat, uint32_t time,
235+                            uint32_t button, uint32_t state)
236+{
237+}
238+
239+/* Wayland Seat Interface */
240+void swc_seat_get_pointer(struct wl_client * client,
241+                          struct wl_resource * resource, uint32_t id)
242+{
243+    struct wl_resource * client_resource;
244+    struct swc_seat * seat = resource->data;
245+    struct wl_pointer * pointer = &seat->pointer;
246+
247+    /* pointer interface? */
248+    client_resource = wl_client_add_object(client, &wl_pointer_interface,
249+                                           NULL, id, seat);
250+    client_resource->destroy = &swc_unbind_resource;
251+
252+    wl_list_insert(&pointer->resource_list, &client_resource->link);
253+
254+    if (pointer->focus && pointer->focus->resource.client == client)
255+    {
256+        //wl_pointer_set_focus(pointer, pointer->focus);
257+    }
258+}
259+
260+void swc_seat_get_keyboard(struct wl_client * client,
261+                           struct wl_resource * resource, uint32_t id)
262+{
263+    struct wl_resource * client_resource;
264+    struct swc_seat * seat = resource->data;
265+    struct wl_keyboard * keyboard = &seat->keyboard;
266+
267+    client_resource = wl_client_add_object(client, &wl_keyboard_interface,
268+                                           NULL, id, seat);
269+    client_resource->destroy = &swc_unbind_resource;
270+
271+    wl_list_insert(&keyboard->resource_list, &client_resource->link);
272+
273+    wl_keyboard_send_keymap(client_resource, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
274+                            seat->xkb.keymap.fd, seat->xkb.keymap.size);
275+
276+    if (keyboard->focus && keyboard->focus->resource.client == client)
277+        wl_keyboard_set_focus(keyboard, keyboard->focus);
278+}
279+
280+void swc_seat_get_touch(struct wl_client * client,
281+                        struct wl_resource * resource, uint32_t id)
282+{
283+    /*
284+    struct wl_resource * client_resource;
285+    struct swc_seat * seat = resource->data;
286+    struct wl_touch * touch = &seat->touch;
287+
288+    client_resource = wl_client_add_object(client, &wl_touch_interface,
289+                                           NULL, id, seat);
290+    client_resource->destroy = &swc_unbind_resource;
291+
292+    wl_list_insert(&touch->resource_list, &client_resource->link);
293+    */
294+}
295+
A seat.h
+59, -0
 1@@ -0,0 +1,59 @@
 2+#ifndef SWC_SEAT_H
 3+#define SWC_SEAT_H 1
 4+
 5+#include "xkb.h"
 6+
 7+#include <stdint.h>
 8+#include <stdbool.h>
 9+#include <libudev.h>
10+#include <wayland-server.h>
11+
12+struct swc_seat
13+{
14+    struct wl_seat wayland;
15+
16+    char * name;
17+
18+    struct swc_xkb xkb;
19+
20+    struct wl_keyboard keyboard;
21+    struct wl_pointer pointer;
22+
23+    uint32_t active_modifiers;
24+    uint32_t capabilities;
25+
26+    struct wl_list devices;
27+};
28+
29+bool swc_seat_initialize(struct swc_seat * seat, struct udev * udev,
30+                         const char * seat_name);
31+
32+void swc_seat_finish(struct swc_seat * seat);
33+
34+void swc_seat_add_globals(struct swc_seat * seat, struct wl_display * display);
35+
36+void swc_seat_add_event_sources(struct swc_seat * seat,
37+                                struct wl_event_loop * event_loop);
38+
39+void swc_seat_add_devices(struct swc_seat * seat, struct udev * udev);
40+
41+void swc_seat_handle_key(struct swc_seat * seat, uint32_t time, uint32_t key,
42+                         uint32_t state);
43+
44+void swc_seat_handle_button(struct swc_seat * seat, uint32_t time,
45+                            uint32_t button, uint32_t state);
46+
47+/* Wayland Seat Interface */
48+extern struct wl_seat_interface swc_seat_interface;
49+
50+void swc_seat_get_pointer(struct wl_client * client,
51+                          struct wl_resource * resource, uint32_t id);
52+
53+void swc_seat_get_keyboard(struct wl_client * client,
54+                           struct wl_resource * resource, uint32_t id);
55+
56+void swc_seat_get_touch(struct wl_client * client,
57+                        struct wl_resource * resource, uint32_t id);
58+
59+#endif
60+
+154, -0
  1@@ -0,0 +1,154 @@
  2+#include "surface.h"
  3+#include "event.h"
  4+
  5+#include <stdio.h>
  6+
  7+struct wl_surface_interface swc_surface_interface = {
  8+    .destroy = &swc_surface_destroy,
  9+    .attach = &swc_surface_attach,
 10+    .damage = &swc_surface_damage,
 11+    .frame = &swc_surface_frame,
 12+    .set_opaque_region = &swc_surface_set_opaque_region,
 13+    .set_input_region = &swc_surface_set_input_region,
 14+    .commit = &swc_surface_commit,
 15+};
 16+
 17+static void state_initialize(struct swc_surface_state * state)
 18+{
 19+    state->buffer = NULL;
 20+
 21+    pixman_region32_init(&state->damage);
 22+    pixman_region32_init(&state->opaque);
 23+    pixman_region32_init(&state->input);
 24+
 25+    wl_list_init(&state->frame_callbacks);
 26+}
 27+
 28+bool swc_surface_initialize(struct swc_surface * surface)
 29+{
 30+    state_initialize(&surface->state);
 31+    state_initialize(&surface->pending.state);
 32+
 33+    wl_signal_init(&surface->event_signal);
 34+
 35+    surface->output_mask = 0;
 36+
 37+    return true;
 38+}
 39+
 40+void swc_surface_finish(struct swc_surface * surface)
 41+{
 42+}
 43+
 44+void swc_surface_destroy(struct wl_client * client,
 45+                         struct wl_resource * resource)
 46+{
 47+    wl_resource_destroy(resource);
 48+}
 49+
 50+void swc_surface_attach(struct wl_client * client,
 51+                        struct wl_resource * resource,
 52+                        struct wl_resource * buffer_resource,
 53+                        int32_t x,
 54+                        int32_t y)
 55+{
 56+    struct swc_surface * surface = resource->data;
 57+    struct wl_buffer * buffer = buffer_resource->data;
 58+
 59+    printf("surface_attach\n");
 60+
 61+    surface->pending.state.buffer = buffer;
 62+    surface->pending.x = x;
 63+    surface->pending.y = y;
 64+
 65+    surface->geometry.width = buffer->width;
 66+    surface->geometry.height = buffer->height;
 67+}
 68+
 69+void swc_surface_damage(struct wl_client * client,
 70+                        struct wl_resource * resource,
 71+                        int32_t x, int32_t y,
 72+                        int32_t width, int32_t height)
 73+{
 74+    printf("surface_damage\n");
 75+    struct swc_surface * surface = resource->data;
 76+
 77+    pixman_region32_union_rect(&surface->pending.state.damage,
 78+                               &surface->pending.state.damage,
 79+                               x, y, width, height);
 80+}
 81+
 82+void swc_surface_frame(struct wl_client * client,
 83+                       struct wl_resource * resource,
 84+                       uint32_t id)
 85+{
 86+    struct swc_surface * surface = resource->data;
 87+    struct wl_resource * callback_resource;
 88+
 89+    printf("surface_frame\n");
 90+
 91+    callback_resource = wl_client_add_object(client, &wl_callback_interface,
 92+                                             NULL, id, NULL);
 93+    wl_list_insert(surface->pending.state.frame_callbacks.prev, &resource->link);
 94+}
 95+
 96+void swc_surface_set_opaque_region(struct wl_client * client,
 97+                                   struct wl_resource * resource,
 98+                                   struct wl_resource * region_resource)
 99+{
100+    struct swc_surface * surface = resource->data;
101+
102+    printf("surface_set_opaque_region\n");
103+
104+    if (region_resource)
105+    {
106+    }
107+    else
108+    {
109+    }
110+}
111+
112+void swc_surface_set_input_region(struct wl_client * client,
113+                                  struct wl_resource * resource,
114+                                  struct wl_resource * region)
115+{
116+    printf("surface_set_input_region\n");
117+}
118+
119+void swc_surface_commit(struct wl_client * client,
120+                        struct wl_resource * resource)
121+{
122+    struct swc_surface * surface = resource->data;
123+    struct swc_event event;
124+
125+    printf("surface_commit\n");
126+
127+    event.data = surface;
128+
129+    if (surface->pending.state.buffer != surface->state.buffer)
130+    {
131+        surface->state.buffer = surface->pending.state.buffer;
132+        event.type = SWC_SURFACE_ATTACH;
133+        wl_signal_emit(&surface->event_signal, &event);
134+    }
135+
136+    pixman_region32_union(&surface->state.damage, &surface->state.damage,
137+                          &surface->pending.state.damage);
138+    pixman_region32_intersect_rect(&surface->state.damage,
139+                                   &surface->state.damage, 0, 0,
140+                                   surface->geometry.width,
141+                                   surface->geometry.height);
142+
143+
144+    wl_list_insert_list(&surface->state.frame_callbacks,
145+                        &surface->pending.state.frame_callbacks);
146+
147+    /* Reset pending state */
148+    pixman_region32_clear(&surface->pending.state.damage);
149+    surface->pending.state.buffer = surface->state.buffer;
150+    wl_list_init(&surface->pending.state.frame_callbacks);
151+
152+    event.type = SWC_SURFACE_REPAINT;
153+    wl_signal_emit(&surface->event_signal, &event);
154+}
155+
+93, -0
 1@@ -0,0 +1,93 @@
 2+#ifndef SWC_SURFACE_H
 3+#define SWC_SURFACE_H 1
 4+
 5+#include "surface_state.h"
 6+
 7+#include <stdbool.h>
 8+#include <wayland-server.h>
 9+#include <pixman.h>
10+
11+enum swc_surface_event
12+{
13+    SWC_SURFACE_ATTACH,
14+    SWC_SURFACE_REPAINT
15+};
16+
17+struct swc_surface_state
18+{
19+    struct wl_buffer * buffer;
20+
21+    /* The region that needs to be repainted */
22+    pixman_region32_t damage;
23+
24+    /* ? */
25+    pixman_region32_t opaque;
26+
27+    /* ? */
28+    pixman_region32_t input;
29+
30+    struct wl_list frame_callbacks;
31+};
32+
33+struct swc_surface
34+{
35+    struct wl_surface wayland;
36+
37+    struct swc_surface_state state;
38+
39+    union swc_renderer_surface_state renderer_state;
40+    struct swc_compositor_surface_state compositor_state;
41+
42+    struct
43+    {
44+        struct swc_surface_state state;
45+        int32_t x, y;
46+    } pending;
47+
48+    struct
49+    {
50+        uint32_t width, height;
51+    } geometry;
52+
53+    uint32_t output_mask;
54+
55+    struct wl_signal event_signal;
56+    struct wl_list link;
57+};
58+
59+bool swc_surface_initialize(struct swc_surface * surface);
60+
61+void swc_surface_finish(struct swc_surface * surface);
62+
63+extern struct wl_surface_interface swc_surface_interface;
64+
65+void swc_surface_destroy(struct wl_client * client,
66+                         struct wl_resource * resource);
67+
68+void swc_surface_attach(struct wl_client * client,
69+                        struct wl_resource * resource,
70+                        struct wl_resource * buffer_resource,
71+                        int32_t x, int32_t y);
72+
73+void swc_surface_damage(struct wl_client * client,
74+                        struct wl_resource * resource,
75+                        int32_t x, int32_t y,
76+                        int32_t width, int32_t height);
77+
78+void swc_surface_frame(struct wl_client * client,
79+                       struct wl_resource * resource,
80+                       uint32_t callback);
81+
82+void swc_surface_set_opaque_region(struct wl_client * client,
83+                                   struct wl_resource * resource,
84+                                   struct wl_resource * region_resource);
85+
86+void swc_surface_set_input_region(struct wl_client * client,
87+                                  struct wl_resource * resource,
88+                                  struct wl_resource * region_resource);
89+
90+void swc_surface_commit(struct wl_client * client,
91+                        struct wl_resource * resource);
92+
93+#endif
94+
+29, -0
 1@@ -0,0 +1,29 @@
 2+#ifndef SWC_SURFACE_STATE_H
 3+#define SWC_SURFACE_STATE_H 1
 4+
 5+#include "i915/bo.h"
 6+
 7+#include <wayland-server.h>
 8+#include <pixman.h>
 9+
10+union swc_renderer_surface_state
11+{
12+    struct
13+    {
14+        pixman_image_t * image;
15+    } shm;
16+    struct
17+    {
18+        struct i915_bo bo;
19+        uint32_t pitch;
20+    } drm;
21+};
22+
23+struct swc_compositor_surface_state
24+{
25+    struct swc_compositor * compositor;
26+    struct wl_listener event_listener;
27+};
28+
29+#endif
30+
+34, -0
 1@@ -0,0 +1,34 @@
 2+#include <stdbool.h>
 3+#include <stdio.h>
 4+#include <wayland-client.h>
 5+
 6+void registry_handle_global(void * data, struct wl_registry * wl_registry,
 7+                            uint32_t name, const char * interface,
 8+                            uint32_t version)
 9+{
10+    printf("handle global\n");
11+    printf("\tinterface: %s\n", interface);
12+}
13+
14+static const struct wl_registry_listener registry_listener = {
15+    .global = &registry_handle_global
16+};
17+
18+int main(int argc, char * argv[])
19+{
20+    struct wl_display * display;
21+    struct wl_registry * registry;
22+    bool running = true;
23+
24+    display = wl_display_connect(NULL);
25+    registry = wl_display_get_registry(display);
26+
27+    wl_registry_add_listener(registry, &registry_listener, NULL);
28+    wl_display_dispatch(display);
29+
30+    while (running)
31+    {
32+        wl_display_dispatch_pending(display);
33+        wl_display_flush(display);
34+    }
35+}
+13, -0
 1@@ -0,0 +1,13 @@
 2+# testwm/Makefile.am
 3+
 4+AM_CFLAGS = -I.. $(pixman_CFLAGS)
 5+
 6+bin_PROGRAMS = testwm
 7+
 8+testwm_SOURCES = \
 9+	main.c \
10+	shell.c shell.h \
11+	shell_surface.c shell_surface.h
12+
13+testwm_LDADD = ../libswc.la $(wayland_server_LIBS)
14+
+173, -0
  1@@ -0,0 +1,173 @@
  2+#include "shell.h"
  3+
  4+#include <compositor.h>
  5+
  6+#include <stdio.h>
  7+#include <stdlib.h>
  8+#include <signal.h>
  9+#include <unistd.h>
 10+#include <sys/wait.h>
 11+
 12+#include <wayland-server.h>
 13+#include <xkbcommon/xkbcommon-keysyms.h>
 14+
 15+const char socket_name[] = "wayland-0";
 16+
 17+void handle_terminate(uint32_t time, uint32_t value, void * data)
 18+{
 19+    struct wl_display * display = data;
 20+    printf("handling terminate\n");
 21+    wl_display_terminate(display);
 22+}
 23+
 24+void handle_switch_vt(uint32_t time, uint32_t value, void * data)
 25+{
 26+    struct swc_tty * tty = data;
 27+    uint32_t vt = value - XKB_KEY_XF86Switch_VT_1 + 1;
 28+    printf("handle switch vt%u\n", vt);
 29+    swc_tty_switch_vt(tty, value - XKB_KEY_XF86Switch_VT_1 + 1);
 30+}
 31+
 32+void handle_test_shm(uint32_t time, uint32_t value, void * data)
 33+{
 34+    printf("handle test shm\n");
 35+    if (fork() == 0)
 36+    {
 37+        printf("launching shm\n");
 38+        execlp("/home/michael/scm/freedesktop/weston/clients/simple-shm", "simple-shm", NULL);
 39+        exit(EXIT_SUCCESS);
 40+    }
 41+}
 42+
 43+void handle_test_term(uint32_t time, uint32_t value, void * data)
 44+{
 45+    printf("handle test term\n");
 46+    if (fork() == 0)
 47+    {
 48+        printf("launching term\n");
 49+        execlp("weston-terminal", "weston-terminal", NULL);
 50+        exit(EXIT_SUCCESS);
 51+    }
 52+}
 53+
 54+void handle_test_info(uint32_t time, uint32_t value, void * data)
 55+{
 56+    printf("handle test info\n");
 57+    if (fork() == 0)
 58+    {
 59+        printf("launching info\n");
 60+        execlp("weston-info", "weston-info", NULL);
 61+        exit(EXIT_SUCCESS);
 62+    }
 63+}
 64+
 65+void handle_test_egl(uint32_t time, uint32_t value, void * data)
 66+{
 67+    printf("handle test egl\n");
 68+    if (fork() == 0)
 69+    {
 70+        printf("launching info\n");
 71+        execlp("/home/michael/scm/freedesktop/weston/clients/simple-egl", "simple-egl", NULL);
 72+        exit(EXIT_SUCCESS);
 73+    }
 74+}
 75+
 76+void handle_flip(uint32_t time, uint32_t value, void * data)
 77+{
 78+    struct swc_compositor * compositor = data;
 79+    struct swc_output * output;
 80+
 81+    output = wl_container_of(compositor->outputs.next, output, link);
 82+
 83+    printf("output: 0x%x\n", output);
 84+    printf("output id: %u\n", output->id);
 85+    printf("compositor: 0x%x\n", compositor);
 86+    printf("handle flip\n");
 87+    swc_renderer_repaint_output(&compositor->renderer, output, &compositor->surfaces);
 88+    swc_output_switch_buffer(output);
 89+}
 90+
 91+int handle_sigint(int signal_number, void * data)
 92+{
 93+    struct wl_display * display = data;
 94+    printf("handle sigint\n");
 95+    wl_display_terminate(display);
 96+
 97+    return 1;
 98+}
 99+
100+int handle_sigchld(int signal_number, void * data)
101+{
102+    printf("handle SIGCHLD\n");
103+    while (waitpid(-1, NULL, WNOHANG) != -1);
104+
105+    return 1;
106+}
107+
108+int main(int argc, char * argv[])
109+{
110+    struct wl_display * display;
111+    struct swc_compositor compositor;
112+    struct wl_event_loop * event_loop;
113+    struct wl_event_source * sigint_source, * sigchld_source;
114+    xkb_keysym_t keysym;
115+
116+    //struct shell shell;
117+
118+    display = wl_display_create();
119+
120+    wl_display_init_shm(display);
121+    wl_data_device_manager_init(display);
122+
123+    event_loop = wl_display_get_event_loop(display);
124+    sigint_source = wl_event_loop_add_signal(event_loop, SIGINT, &handle_sigint,
125+                                             display);
126+
127+    sigchld_source = wl_event_loop_add_signal(event_loop, SIGCHLD, &handle_sigchld,
128+                                              NULL);
129+
130+    swc_compositor_initialize(&compositor, display);
131+    swc_compositor_add_globals(&compositor, display);
132+
133+    //shell_initialize(&shell, display);
134+
135+    swc_compositor_add_key_binding(&compositor,
136+        MOD_CTRL | MOD_ALT, XKB_KEY_BackSpace, &handle_terminate, display);
137+
138+    for (keysym = XKB_KEY_XF86Switch_VT_1;
139+         keysym <= XKB_KEY_XF86Switch_VT_12;
140+         ++keysym)
141+    {
142+        swc_compositor_add_key_binding(&compositor, MOD_ANY, keysym,
143+                                       &handle_switch_vt, &compositor.tty);
144+    }
145+
146+    swc_compositor_add_key_binding(&compositor, MOD_SUPER, XKB_KEY_Return,
147+                                   &handle_test_term, NULL);
148+
149+    swc_compositor_add_key_binding(&compositor, MOD_SUPER, XKB_KEY_1,
150+                                   &handle_test_info, NULL);
151+
152+    swc_compositor_add_key_binding(&compositor, MOD_SUPER, XKB_KEY_2,
153+                                   &handle_test_shm, NULL);
154+
155+    swc_compositor_add_key_binding(&compositor, MOD_SUPER, XKB_KEY_3,
156+                                   &handle_test_egl, NULL);
157+
158+    swc_compositor_add_key_binding(&compositor, MOD_SUPER, XKB_KEY_0,
159+                                   &handle_flip, &compositor);
160+
161+    wl_display_add_socket(display, socket_name);
162+    setenv("WAYLAND_DISPLAY", socket_name, 1);
163+
164+    wl_display_run(display);
165+
166+    /* Cleanup */
167+    wl_event_source_remove(sigint_source);
168+    wl_event_source_remove(sigchld_source);
169+    swc_compositor_finish(&compositor);
170+    wl_display_destroy(display);
171+
172+    return EXIT_SUCCESS;
173+}
174+
+29, -0
 1@@ -0,0 +1,29 @@
 2+#include "shell.h"
 3+
 4+#include "shell_surface.h"
 5+
 6+static void get_shell_surface(struct wl_client * client,
 7+                              struct wl_resource * resource, uint32_t id,
 8+                              struct wl_resource * surface)
 9+{
10+    wl_client_add_object(client, &wl_shell_surface_interface,
11+                         &shell_surface_implementation, id, surface->data);
12+}
13+
14+struct wl_shell_interface shell_implementation = {
15+    .get_shell_surface = &get_shell_surface
16+};
17+
18+static void bind_shell(struct wl_client * client, void * data, uint32_t version,
19+                       uint32_t id)
20+{
21+    wl_client_add_object(client, &wl_shell_interface, &shell_implementation,
22+                         id, NULL);
23+}
24+
25+void shell_initialize(struct shell * shell, struct wl_display * display)
26+{
27+    wl_display_add_global(display, &wl_shell_interface, &shell_implementation,
28+                          &bind_shell);
29+}
30+
+15, -0
 1@@ -0,0 +1,15 @@
 2+#ifndef TESTWM_SHELL_H
 3+#define TESTWM_SHELL_H 1
 4+
 5+#include <wayland-server.h>
 6+
 7+struct shell
 8+{
 9+};
10+
11+extern struct wl_shell_interface shell_implementation;
12+
13+void shell_initialize(struct shell * shell, struct wl_display * display);
14+
15+#endif
16+
+79, -0
 1@@ -0,0 +1,79 @@
 2+#include "shell_surface.h"
 3+
 4+#include <stdlib.h>
 5+#include <wayland-server.h>
 6+
 7+static void pong(struct wl_client * client, struct wl_resource * resource,
 8+                 uint32_t serial)
 9+{
10+}
11+
12+static void move(struct wl_client * client, struct wl_resource * resource,
13+                 struct wl_resource * seat_resource, uint32_t serial)
14+{
15+}
16+
17+static void resize(struct wl_client * client, struct wl_resource * resource,
18+                   struct wl_resource * seat_resource, uint32_t serial,
19+                   uint32_t edges)
20+{
21+}
22+
23+static void set_toplevel(struct wl_client * client,
24+                         struct wl_resource * resource)
25+{
26+}
27+
28+static void set_transient(struct wl_client * client,
29+                          struct wl_resource * resource,
30+                          struct wl_resource * parent_resource,
31+                          int32_t x, int32_t y, uint32_t flags)
32+{
33+}
34+
35+static void set_fullscreen(struct wl_client * client,
36+                           struct wl_resource * resource, uint32_t method,
37+                           uint32_t framerate, struct wl_resource * output)
38+{
39+}
40+
41+static void set_popup(struct wl_client * client, struct wl_resource * resource,
42+                      struct wl_resource * seat_resource, uint32_t serial,
43+                      struct wl_resource * parent_resource,
44+                      int32_t x, int32_t y, uint32_t flags)
45+{
46+}
47+
48+static void set_maximized(struct wl_client * client,
49+                          struct wl_resource * resource,
50+                          struct wl_resource * output)
51+{
52+}
53+
54+static void set_class(struct wl_client * client, struct wl_resource * resource,
55+                      const char * class_)
56+{
57+}
58+
59+struct wl_shell_surface_interface shell_surface_implementation = {
60+    .pong = &pong,
61+    .move = &move,
62+    .resize = &resize,
63+    .set_toplevel = &set_toplevel,
64+    .set_transient = &set_transient,
65+    .set_fullscreen = &set_fullscreen,
66+    .set_popup = &set_popup,
67+    .set_maximized = &set_maximized,
68+    .set_class = &set_class
69+};
70+
71+struct shell_surface * shell_surface_create(struct swc_surface * surface)
72+{
73+    struct shell_surface * shell_surface;
74+
75+    shell_surface = malloc(sizeof *shell_surface);
76+    shell_surface->surface = surface;
77+
78+    return shell_surface;
79+}
80+
+13, -0
 1@@ -0,0 +1,13 @@
 2+#ifndef TESTWM_SHELL_SURFACE_H
 3+#define TESTWM_SHELL_SURFACE_H 1
 4+
 5+struct shell_surface
 6+{
 7+    struct swc_surface * surface;
 8+    struct wl_resource * resource;
 9+};
10+
11+extern struct wl_shell_surface_interface shell_surface_implementation;
12+
13+#endif
14+
+151, -0
  1@@ -0,0 +1,151 @@
  2+#include "compositor.h"
  3+
  4+#include <stdio.h>
  5+#include <stdlib.h>
  6+#include <signal.h>
  7+#include <unistd.h>
  8+#include <sys/wait.h>
  9+
 10+#include <wayland-server.h>
 11+#include <xkbcommon/xkbcommon-keysyms.h>
 12+
 13+const char socket_name[] = "wayland-0";
 14+
 15+static void get_shell_surface(struct wl_client * client,
 16+                              struct wl_resource * resource, uint32_t id,
 17+                              struct wl_resource * surface)
 18+{
 19+    wl_client_add_object(client, &wl_shell_surface_interface, NULL, id, surface->data);
 20+}
 21+
 22+struct wl_shell_interface shell_interface = {
 23+    .get_shell_surface = &get_shell_surface
 24+};
 25+
 26+void handle_terminate(uint32_t time, uint32_t value, void * data)
 27+{
 28+    struct wl_display * display = data;
 29+    printf("handling terminate\n");
 30+    wl_display_terminate(display);
 31+}
 32+
 33+void handle_switch_vt(uint32_t time, uint32_t value, void * data)
 34+{
 35+    struct swc_tty * tty = data;
 36+    uint32_t vt = value - XKB_KEY_XF86Switch_VT_1 + 1;
 37+    printf("handle switch vt%u\n", vt);
 38+    swc_tty_switch_vt(tty, value - XKB_KEY_XF86Switch_VT_1 + 1);
 39+}
 40+
 41+void handle_test_shm(uint32_t time, uint32_t value, void * data)
 42+{
 43+    printf("handle test shm\n");
 44+    if (fork() == 0)
 45+    {
 46+        printf("launching shm\n");
 47+        execlp("/home/michael/scm/freedesktop/weston/clients/simple-shm", "simple-shm", NULL);
 48+        exit(EXIT_SUCCESS);
 49+    }
 50+}
 51+
 52+void handle_test_term(uint32_t time, uint32_t value, void * data)
 53+{
 54+    printf("handle test term\n");
 55+    if (fork() == 0)
 56+    {
 57+        printf("launching term\n");
 58+        execlp("weston-terminal", "weston-terminal", NULL);
 59+        exit(EXIT_SUCCESS);
 60+    }
 61+}
 62+
 63+void handle_test_info(uint32_t time, uint32_t value, void * data)
 64+{
 65+    printf("handle test term\n");
 66+    if (fork() == 0)
 67+    {
 68+        printf("launching info\n");
 69+        execlp("weston-info", "weston-info", NULL);
 70+        exit(EXIT_SUCCESS);
 71+    }
 72+}
 73+
 74+int handle_sigint(int signal_number, void * data)
 75+{
 76+    struct wl_display * display = data;
 77+    printf("handle sigint\n");
 78+    wl_display_terminate(display);
 79+
 80+    return 1;
 81+}
 82+
 83+int handle_sigchld(int signal_number, void * data)
 84+{
 85+    printf("handle SIGCHLD\n");
 86+    while (waitpid(-1, NULL, WNOHANG) != -1);
 87+}
 88+
 89+static void bind_shell(struct wl_client * client, void * data, uint32_t version, uint32_t id)
 90+{
 91+    wl_client_add_object(client, &wl_shell_interface, &shell_interface, id, NULL);
 92+}
 93+
 94+int main(int argc, char * argv[])
 95+{
 96+    struct wl_display * display;
 97+    struct swc_compositor compositor;
 98+    struct wl_event_loop * event_loop;
 99+    struct wl_event_source * sigint_source, * sigchld_source;
100+    xkb_keysym_t keysym;
101+
102+    display = wl_display_create();
103+
104+    wl_display_init_shm(display);
105+    wl_data_device_manager_init(display);
106+
107+    event_loop = wl_display_get_event_loop(display);
108+    sigint_source = wl_event_loop_add_signal(event_loop, SIGINT, &handle_sigint,
109+                                             display);
110+
111+    sigchld_source = wl_event_loop_add_signal(event_loop, SIGCHLD, &handle_sigchld,
112+                                              NULL);
113+
114+    swc_compositor_initialize(&compositor, display);
115+    swc_compositor_add_globals(&compositor, display);
116+
117+    wl_display_add_global(display, &wl_shell_interface, NULL, &bind_shell);
118+
119+    swc_compositor_add_key_binding(&compositor,
120+        MOD_CTRL | MOD_ALT, XKB_KEY_BackSpace, &handle_terminate, display);
121+
122+    for (keysym = XKB_KEY_XF86Switch_VT_1;
123+         keysym <= XKB_KEY_XF86Switch_VT_12;
124+         ++keysym)
125+    {
126+        swc_compositor_add_key_binding(&compositor, MOD_ANY, keysym,
127+                                       &handle_switch_vt, &compositor.tty);
128+    }
129+
130+    swc_compositor_add_key_binding(&compositor, MOD_SUPER, XKB_KEY_Return,
131+                                   &handle_test_term, NULL);
132+
133+    swc_compositor_add_key_binding(&compositor, MOD_SUPER, XKB_KEY_1,
134+                                   &handle_test_info, NULL);
135+
136+    swc_compositor_add_key_binding(&compositor, MOD_SUPER, XKB_KEY_2,
137+                                   &handle_test_shm, NULL);
138+
139+    wl_display_add_socket(display, socket_name);
140+    setenv("WAYLAND_DISPLAY", socket_name, 1);
141+
142+    wl_display_run(display);
143+
144+    /* Cleanup */
145+    wl_event_source_remove(sigint_source);
146+    wl_event_source_remove(sigchld_source);
147+    swc_compositor_finish(&compositor);
148+    wl_display_destroy(display);
149+
150+    return EXIT_SUCCESS;
151+}
152+
A tty.c
+221, -0
  1@@ -0,0 +1,221 @@
  2+/* swc: tty.c
  3+ *
  4+ * Copyright © 2012 Michael Forney
  5+ *
  6+ * Based in part upon tty.c from weston, which is:
  7+ *
  8+ *      Copyright © 2010 Intel Corporation
  9+ *
 10+ * Permission is hereby granted, free of charge, to any person obtaining a copy
 11+ * of this software and associated documentation files (the "Software"), to
 12+ * deal in the Software without restriction, including without limitation the
 13+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 14+ * sell copies of the Software, and to permit persons to whom the Software is
 15+ * furnished to do so, subject to the following conditions:
 16+ *
 17+ * The above copyright notice and this permission notice shall be included in
 18+ * all copies or substantial portions of the Software.
 19+ *
 20+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 21+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 22+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 23+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 24+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 25+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 26+ * IN THE SOFTWARE.
 27+ */
 28+
 29+#include <stdlib.h>
 30+#include <stdio.h>
 31+#include <unistd.h>
 32+#include <fcntl.h>
 33+#include <sys/ioctl.h>
 34+#include <linux/vt.h>
 35+#include <linux/kd.h>
 36+
 37+#include <wayland-server.h>
 38+
 39+#include "tty.h"
 40+#include "event.h"
 41+
 42+static void restore_tty(struct swc_tty * tty);
 43+static int handle_vt_signal(int signal_number, void * data);
 44+
 45+bool swc_tty_initialize(struct swc_tty * tty,
 46+                        struct wl_event_loop * event_loop,
 47+                        uint8_t tty_number)
 48+{
 49+    struct vt_stat state;
 50+    char tty_device[16];
 51+    struct vt_mode mode;
 52+
 53+    wl_signal_init(&tty->event_signal);
 54+
 55+    if (tty_number == 0)
 56+    {
 57+        char * vt_string = getenv("XDG_VTNR");
 58+        if (vt_string)
 59+        {
 60+            char * end;
 61+            tty_number = strtoul(vt_string, &end, 10);
 62+            if (*end != '\0')
 63+                tty_number = 0;
 64+        }
 65+    }
 66+
 67+    /* If we still don't have a VT number. */
 68+    if (tty_number == 0)
 69+    {
 70+        printf("don't know which VT to run on\n");
 71+        goto error_base;
 72+    }
 73+
 74+    snprintf(tty_device, sizeof(tty_device), "/dev/tty%u", tty_number);
 75+
 76+    /* Open the TTY. */
 77+    tty->fd = open(tty_device, O_RDWR | O_NOCTTY | O_CLOEXEC);
 78+
 79+    if (tty->fd == -1)
 80+    {
 81+        printf("couldn't open tty\n");
 82+        goto error_base;
 83+    }
 84+
 85+    tty->vt = tty_number;
 86+
 87+    /* Determine the current VT state. */
 88+    if (ioctl(tty->fd, VT_GETSTATE, &state) != 0)
 89+    {
 90+        printf("could not determine starting vt\n");
 91+        goto error_tty;
 92+    }
 93+
 94+    tty->original_state.vt = state.v_active;
 95+    printf("starting vt: %u\n", tty->original_state.vt);
 96+
 97+    /* Switch to the new VT if necessary. */
 98+    if (tty->original_state.vt != tty->vt)
 99+    {
100+        if (ioctl(tty->fd, VT_ACTIVATE, tty->vt) != 0
101+            || ioctl(tty->fd, VT_WAITACTIVE, tty->vt) != 0)
102+        {
103+            printf("couldn't switch to vt%u\n", tty->vt);
104+            goto error_tty;
105+        }
106+    }
107+
108+    tty->active = true;
109+
110+    /* Save current kb_mode. */
111+    if (ioctl(tty->fd, KDGKBMODE, &tty->original_state.kb_mode) != 0)
112+    {
113+        printf("couldn't determine kb_mode of vt%u\n", tty->vt);
114+        goto error_tty;
115+    }
116+
117+    /* Turn off keyboard, we will use evdev for input. */
118+    if (ioctl(tty->fd, KDSKBMODE, K_OFF) != 0)
119+    {
120+        printf("couldn't set kb_mode of vt%u to K_OFF\n", tty->vt);
121+        goto error_tty;
122+    }
123+
124+    /* Set VT to graphics mode. */
125+    if (ioctl(tty->fd, KDSETMODE, KD_GRAPHICS) != 0)
126+    {
127+        printf("couldn't set mode of vt%u to KD_GRAPHICS\n", tty->vt);
128+        goto error_kdkbmode;
129+    }
130+
131+    mode = (struct vt_mode) {
132+        .mode = VT_PROCESS,
133+        .relsig = SIGUSR1,
134+        .acqsig = SIGUSR1
135+    };
136+
137+    /* Set up VT switching handler. */
138+    if (ioctl(tty->fd, VT_SETMODE, &mode) != 0)
139+    {
140+        printf("could not set VT mode on vt%u\n", tty->vt);
141+        goto error_kdmode;
142+    }
143+
144+    tty->vt_source = wl_event_loop_add_signal(event_loop, SIGUSR1,
145+                                              &handle_vt_signal, tty);
146+
147+    if (!tty->vt_source)
148+    {
149+        printf("could not create VT event source\n");
150+        goto error_vtmode;
151+    }
152+
153+    return true;
154+
155+  error_vtmode:
156+    mode = (struct vt_mode) { .mode = VT_AUTO };
157+    ioctl(tty->fd, VT_SETMODE, &mode);
158+  error_kdmode:
159+    ioctl(tty->fd, KDSETMODE, KD_TEXT);
160+  error_kdkbmode:
161+    ioctl(tty->fd, KDSKBMODE, tty->original_state.kb_mode);
162+  error_tty:
163+    close(tty->fd);
164+  error_base:
165+    return false;
166+}
167+
168+void swc_tty_finish(struct swc_tty * tty)
169+{
170+    wl_event_source_remove(tty->vt_source);
171+    restore_tty(tty);
172+    close(tty->fd);
173+}
174+
175+void swc_tty_switch_vt(struct swc_tty * tty, uint32_t vt)
176+{
177+    ioctl(tty->fd, VT_ACTIVATE, vt);
178+}
179+
180+void restore_tty(struct swc_tty * tty)
181+{
182+    struct vt_mode mode = { .mode = VT_AUTO };
183+
184+    if (ioctl(tty->fd, KDSKBMODE, tty->original_state.kb_mode) != 0)
185+        printf("failed to restore keyboard mode\n");
186+    if (ioctl(tty->fd, KDSETMODE, KD_TEXT) != 0)
187+        printf("failed to set mode to KD_TEXT\n");
188+    if (ioctl(tty->fd, VT_SETMODE, &mode) != 0)
189+        printf("failed to restore VT handling\n");
190+    if (tty->vt != tty->original_state.vt
191+        && (ioctl(tty->fd, VT_ACTIVATE, tty->original_state.vt) != 0
192+            || ioctl(tty->fd, VT_WAITACTIVE, tty->original_state.vt) != 0))
193+    {
194+        printf("failed to restore VT\n");
195+    }
196+}
197+
198+static int handle_vt_signal(int signal_number, void * data)
199+{
200+    struct swc_tty * tty = data;
201+    struct swc_event event;
202+
203+    if (tty->active)
204+    {
205+        event.type = SWC_TTY_VT_LEAVE;
206+        wl_signal_emit(&tty->event_signal, &event);
207+
208+        ioctl(tty->fd, VT_RELDISP, 1);
209+        tty->active = false;
210+    }
211+    else
212+    {
213+        ioctl(tty->fd, VT_RELDISP, VT_ACKACQ);
214+        tty->active = true;
215+
216+        event.type = SWC_TTY_VT_ENTER;
217+        wl_signal_emit(&tty->event_signal, &event);
218+    }
219+
220+    return 1;
221+}
222+
A tty.h
+44, -0
 1@@ -0,0 +1,44 @@
 2+#ifndef SWC_TTY_H
 3+#define SWC_TTY_H 1
 4+
 5+#include <stdint.h>
 6+#include <stdbool.h>
 7+#include <signal.h>
 8+
 9+enum swc_tty_event
10+{
11+    SWC_TTY_VT_ENTER = 0,
12+    SWC_TTY_VT_LEAVE
13+};
14+
15+struct swc_tty
16+{
17+    int fd;
18+    uint8_t vt;
19+
20+    bool active;
21+
22+    /* The state of the VT the compositor was started on so we have a state to
23+     * restore to when the compositor closes. */
24+    struct
25+    {
26+        uint8_t vt;
27+        long kb_mode;
28+    } original_state;
29+
30+    /* Receives events when switching from/to the VT the compositor is running on. */
31+    struct wl_event_source * vt_source;
32+
33+    struct wl_signal event_signal;
34+};
35+
36+bool swc_tty_initialize(struct swc_tty * tty,
37+                        struct wl_event_loop * event_loop,
38+                        uint8_t tty_number);
39+
40+void swc_tty_finish(struct swc_tty * tty);
41+
42+void swc_tty_switch_vt(struct swc_tty * tty, uint32_t vt);
43+
44+#endif
45+
A util.c
+10, -0
 1@@ -0,0 +1,10 @@
 2+#include "util.h"
 3+
 4+#include <stdlib.h>
 5+
 6+void swc_unbind_resource(struct wl_resource * resource)
 7+{
 8+    wl_list_remove(&resource->link);
 9+    free(resource);
10+}
11+
A util.h
+20, -0
 1@@ -0,0 +1,20 @@
 2+#ifndef SWC_UTIL_H
 3+#define SWC_UTIL_H 1
 4+
 5+#include <wayland-server.h>
 6+
 7+/*
 8+void swc_object_init(struct wl_object * object,
 9+                     const struct wl_interface * interface,
10+                     const void * implementation, uint32_t id);
11+
12+void swc_resource_init(struct wl_resource * resource,
13+                       struct wl_client * client, 
14+
15+void swc_client_add_object(struct wl_clientstruct wl_resource * resource, );
16+*/
17+
18+void swc_unbind_resource(struct wl_resource * resource);
19+
20+#endif
21+
A xkb.c
+140, -0
  1@@ -0,0 +1,140 @@
  2+#include "xkb.h"
  3+
  4+#include <stdlib.h>
  5+#include <fcntl.h>
  6+#include <unistd.h>
  7+#include <string.h>
  8+#include <sys/mman.h>
  9+
 10+const struct xkb_rule_names rule_names = {
 11+    .layout = "us,us",
 12+    .variant = "dvorak,",
 13+    .options = "grp:alt_shift_toggle"
 14+};
 15+
 16+const char keymap_file_template[] = "swc-xkb-keymap-XXXXXX";
 17+
 18+bool swc_xkb_initialize(struct swc_xkb * xkb)
 19+{
 20+    xkb->context = xkb_context_new(0);
 21+
 22+    if (!xkb->context)
 23+    {
 24+        printf("could not create XKB context\n");
 25+        goto error_base;
 26+    }
 27+
 28+    xkb->keymap.map = xkb_keymap_new_from_names(xkb->context, &rule_names, 0);
 29+
 30+    if (!xkb->keymap.map)
 31+    {
 32+        printf("could not create XKB keymap\n");
 33+        goto error_context;
 34+    }
 35+
 36+    xkb->state = xkb_state_new(xkb->keymap.map);
 37+
 38+    if (!swc_xkb_update_keymap(xkb))
 39+    {
 40+        printf("could not update XKB keymap\n");
 41+        goto error_state;
 42+    }
 43+
 44+    return true;
 45+
 46+  error_state:
 47+    xkb_state_unref(xkb->state);
 48+  error_keymap:
 49+    xkb_keymap_unref(xkb->keymap.map);
 50+  error_context:
 51+    xkb_context_unref(xkb->context);
 52+  error_base:
 53+    return false;
 54+}
 55+
 56+void swc_xkb_finish(struct swc_xkb * xkb)
 57+{
 58+    munmap(xkb->keymap.area, xkb->keymap.size);
 59+    close(xkb->keymap.fd);
 60+    xkb_state_unref(xkb->state);
 61+    xkb_keymap_unref(xkb->keymap.map);
 62+    xkb_context_unref(xkb->context);
 63+}
 64+
 65+bool swc_xkb_update_keymap(struct swc_xkb * xkb)
 66+{
 67+    char * keymap_string;
 68+
 69+    xkb->indices.ctrl
 70+        = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_CTRL);
 71+    xkb->indices.alt
 72+        = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_ALT);
 73+    xkb->indices.super
 74+        = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_LOGO);
 75+    xkb->indices.shift
 76+        = xkb_keymap_mod_get_index(xkb->keymap.map, XKB_MOD_NAME_SHIFT);
 77+
 78+    /* Keymap string */
 79+    {
 80+        const char * keymap_directory = getenv("XDG_RUNTIME_DIR") ?: "/tmp";
 81+        char keymap_path[strlen(keymap_directory) + 1
 82+                         + sizeof keymap_file_template];
 83+
 84+        /* In order to send the keymap to clients, we must first convert it to a
 85+         * string and then mmap it to a file. */
 86+        keymap_string = xkb_keymap_get_as_string(xkb->keymap.map,
 87+                                                 XKB_KEYMAP_FORMAT_TEXT_V1);
 88+
 89+        if (!keymap_string)
 90+        {
 91+            printf("could not get XKB keymap as a string\n");
 92+            goto error_base;
 93+        }
 94+
 95+        sprintf(keymap_path, "%s/%s", keymap_directory, keymap_file_template);
 96+
 97+        xkb->keymap.size = strlen(keymap_string) + 1;
 98+        xkb->keymap.fd = mkostemp(keymap_path, O_CLOEXEC);
 99+
100+        if (xkb->keymap.fd == -1)
101+        {
102+            printf("could not create XKB keymap file\n");
103+            goto error_string;
104+        }
105+
106+        unlink(keymap_path);
107+
108+        if (ftruncate(xkb->keymap.fd, xkb->keymap.size) == -1)
109+        {
110+            printf("could not resize XKB keymap file\n");
111+            goto error_fd;
112+        }
113+
114+        xkb->keymap.area = mmap(NULL, xkb->keymap.size, PROT_READ | PROT_WRITE,
115+            MAP_SHARED, xkb->keymap.fd, 0);
116+
117+        if (xkb->keymap.area == MAP_FAILED)
118+        {
119+            printf("could not mmap XKB keymap string\n");
120+            goto error_fd;
121+        }
122+
123+        strcpy(xkb->keymap.area, keymap_string);
124+
125+        free(keymap_string);
126+    }
127+
128+    return true;
129+
130+  error_fd:
131+    close(xkb->keymap.fd);
132+  error_string:
133+    free(keymap_string);
134+  error_base:
135+    return false;
136+}
137+
138+void swc_xkb_update_key_indices(struct swc_xkb * xkb)
139+{
140+}
141+
A xkb.h
+28, -0
 1@@ -0,0 +1,28 @@
 2+#include <stdbool.h>
 3+#include <xkbcommon/xkbcommon.h>
 4+
 5+struct swc_xkb
 6+{
 7+    struct xkb_context * context;
 8+    struct xkb_state * state;
 9+
10+    struct
11+    {
12+        struct xkb_keymap * map;
13+        int fd;
14+        uint32_t size;
15+        char * area;
16+    } keymap;
17+
18+    struct
19+    {
20+        uint32_t ctrl, alt, super, shift;
21+    } indices;
22+};
23+
24+bool swc_xkb_initialize(struct swc_xkb * xkb);
25+
26+void swc_xkb_finish(struct swc_xkb * xkb);
27+
28+bool swc_xkb_update_keymap(struct swc_xkb * xkb);
29+