commit ba51fad
Michael Forney
·
2013-01-15 10:44:00 +0000 UTC
parent ba51fad
Import
49 files changed,
+4191,
-0
+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+
A
buffer.c
+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+
A
buffer.h
+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+
A
event.h
+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+
A
output.c
+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, ¤t_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+
A
output.h
+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 = ®istry_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, ®istry_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+