Add x11 backend for compositor

This still needs all the bells and whistles from the egl-kms mesa branch,
but it makes it a lot easier to work on wayland.
diff --git a/compositor-drm.c b/compositor-drm.c
index 178941c..608ada9 100644
--- a/compositor-drm.c
+++ b/compositor-drm.c
@@ -37,8 +37,43 @@
 #include "wayland-protocol.h"
 #include "compositor.h"
 
+struct drm_compositor {
+	struct wlsc_compositor base;
+
+	struct udev *udev;
+	struct wl_event_source *drm_source;
+	int drm_fd;
+
+	struct wl_event_source *term_signal_source;
+
+        /* tty handling state */
+	int tty_fd;
+	uint32_t vt_active : 1;
+
+	struct termios terminal_attributes;
+	struct wl_event_source *tty_input_source;
+	struct wl_event_source *enter_vt_source;
+	struct wl_event_source *leave_vt_source;
+};
+
+struct drm_output {
+	struct wlsc_output   base;
+
+	drmModeModeInfo mode;
+	uint32_t crtc_id;
+	uint32_t connector_id;
+	GLuint rbo[2];
+	uint32_t fb_id[2];
+	EGLImageKHR image[2];
+	uint32_t current;	
+};
+
+struct drm_input {
+	struct wlsc_input_device base;
+};
+
 struct evdev_input_device {
-	struct wlsc_input_device *device;
+	struct drm_input *master;
 	struct wl_event_source *source;
 	int tool, new_x, new_y;
 	int base_x, base_y;
@@ -47,16 +82,21 @@
 
 static void evdev_input_device_data(int fd, uint32_t mask, void *data)
 {
+	struct drm_compositor *c;
 	struct evdev_input_device *device = data;
 	struct input_event ev[8], *e, *end;
 	int len, value, dx, dy, absolute_event;
 	int x, y;
 
+	c = (struct drm_compositor *) device->master->base.ec;
+	if (!c->vt_active)
+		return;
+
 	dx = 0;
 	dy = 0;
 	absolute_event = 0;
-	x = device->device->x;
-	y = device->device->y;
+	x = device->master->base.x;
+	y = device->master->base.y;
 
 	len = read(fd, &ev, sizeof ev);
 	if (len < 0 || len % sizeof e[0] != 0) {
@@ -132,24 +172,26 @@
 			case BTN_FORWARD:
 			case BTN_BACK:
 			case BTN_TASK:
-				notify_button(device->device, e->code, value);
+				notify_button(&device->master->base,
+					      e->code, value);
 				break;
 
 			default:
-				notify_key(device->device, e->code, value);
+				notify_key(&device->master->base,
+					   e->code, value);
 				break;
 			}
 		}
 	}
 
 	if (dx != 0 || dy != 0)
-		notify_motion(device->device, x + dx, y + dy);
+		notify_motion(&device->master->base, x + dx, y + dy);
 	if (absolute_event && device->tool)
-		notify_motion(device->device, x, y);
+		notify_motion(&device->master->base, x, y);
 }
 
 static struct evdev_input_device *
-evdev_input_device_create(struct wlsc_input_device *master,
+evdev_input_device_create(struct drm_input *master,
 			  struct wl_display *display, const char *path)
 {
 	struct evdev_input_device *device;
@@ -162,7 +204,7 @@
 	device->tool = 1;
 	device->new_x = 1;
 	device->new_y = 1;
-	device->device = master;
+	device->master = master;
 
 	device->fd = open(path, O_RDONLY);
 	if (device->fd < 0) {
@@ -184,13 +226,52 @@
 	return device;
 }
 
-void
-wlsc_compositor_present_drm(struct wlsc_compositor *ec)
+static void
+drm_input_create(struct drm_compositor *c)
 {
-	struct wlsc_output *output;
+	struct drm_input *input;
+	struct udev_enumerate *e;
+        struct udev_list_entry *entry;
+	struct udev_device *device;
+	const char *path;
 
-	wl_list_for_each(output, &ec->output_list, link) {
-		drmModePageFlip(ec->drm_fd, output->crtc_id,
+	input = malloc(sizeof *input);
+	if (input == NULL)
+		return;
+
+	memset(input, 0, sizeof *input);
+	wlsc_input_device_init(&input->base, &c->base);
+
+	e = udev_enumerate_new(c->udev);
+	udev_enumerate_add_match_subsystem(e, "input");
+	udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1");
+        udev_enumerate_scan_devices(e);
+        udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
+		path = udev_list_entry_get_name(entry);
+		device = udev_device_new_from_syspath(c->udev, path);
+		evdev_input_device_create(input, c->base.wl_display,
+					  udev_device_get_devnode(device));
+	}
+        udev_enumerate_unref(e);
+
+	c->base.input_device = &input->base;
+}
+
+static void
+drm_compositor_present(struct wlsc_compositor *ec)
+{
+	struct drm_compositor *c = (struct drm_compositor *) ec;
+	struct drm_output *output;
+
+	wl_list_for_each(output, &ec->output_list, base.link) {
+		output->current ^= 1;
+
+		glFramebufferRenderbuffer(GL_FRAMEBUFFER,
+					  GL_COLOR_ATTACHMENT0,
+					  GL_RENDERBUFFER,
+					  output->rbo[output->current]);
+
+		drmModePageFlip(c->drm_fd, output->crtc_id,
 				output->fb_id[output->current ^ 1],
 				DRM_MODE_PAGE_FLIP_EVENT, output);
 	}	
@@ -220,9 +301,8 @@
 }
 
 static int
-init_egl(struct wlsc_compositor *ec, struct udev_device *device)
+init_egl(struct drm_compositor *ec, struct udev_device *device)
 {
-	struct wl_event_loop *loop;
 	EGLint major, minor, count;
 	EGLConfig config;
 	PFNEGLGETTYPEDDISPLAYMESA get_typed_display_mesa;
@@ -241,8 +321,8 @@
 		return -1;
 	}
 
-	ec->base.device = strdup(udev_device_get_devnode(device));
-	ec->drm_fd = open(ec->base.device, O_RDWR);
+	ec->base.base.device = strdup(udev_device_get_devnode(device));
+	ec->drm_fd = open(ec->base.base.device, O_RDWR);
 	if (ec->drm_fd < 0) {
 		/* Probably permissions error */
 		fprintf(stderr, "couldn't open %s, skipping\n",
@@ -250,41 +330,39 @@
 		return -1;
 	}
 
-	ec->display = get_typed_display_mesa(EGL_DRM_DISPLAY_TYPE_MESA,
-					     (void *) ec->drm_fd);
-	if (ec->display == NULL) {
+	ec->base.display = get_typed_display_mesa(EGL_DRM_DISPLAY_TYPE_MESA,
+						  (void *) ec->drm_fd);
+	if (ec->base.display == NULL) {
 		fprintf(stderr, "failed to create display\n");
 		return -1;
 	}
 
-	if (!eglInitialize(ec->display, &major, &minor)) {
+	if (!eglInitialize(ec->base.display, &major, &minor)) {
 		fprintf(stderr, "failed to initialize display\n");
 		return -1;
 	}
 
-	if (!eglChooseConfig(ec->display, config_attribs, &config, 1, &count) ||
+	if (!eglChooseConfig(ec->base.display,
+			     config_attribs, &config, 1, &count) ||
 	    count == 0) {
 		fprintf(stderr, "eglChooseConfig() failed\n");
 		return -1;
 	}
 
 	eglBindAPI(EGL_OPENGL_API);
-	ec->context = eglCreateContext(ec->display, config, EGL_NO_CONTEXT, NULL);
-	if (ec->context == NULL) {
+	ec->base.context = eglCreateContext(ec->base.display,
+					    config, EGL_NO_CONTEXT, NULL);
+	if (ec->base.context == NULL) {
 		fprintf(stderr, "failed to create context\n");
 		return -1;
 	}
 
-	if (!eglMakeCurrent(ec->display, EGL_NO_SURFACE, EGL_NO_SURFACE, ec->context)) {
+	if (!eglMakeCurrent(ec->base.display, EGL_NO_SURFACE,
+			    EGL_NO_SURFACE, ec->base.context)) {
 		fprintf(stderr, "failed to make context current\n");
 		return -1;
 	}
 
-	loop = wl_display_get_event_loop(ec->wl_display);
-	ec->drm_source =
-		wl_event_loop_add_fd(loop, ec->drm_fd,
-				     WL_EVENT_READABLE, on_drm_input, ec);
-
 	return 0;
 }
 
@@ -299,11 +377,11 @@
 };
 
 static int
-create_output_for_connector(struct wlsc_compositor *ec,
+create_output_for_connector(struct drm_compositor *ec,
 			    drmModeRes *resources,
 			    drmModeConnector *connector)
 {
-	struct wlsc_output *output;
+	struct drm_output *output;
 	drmModeEncoder *encoder;
 	drmModeModeInfo *mode;
 	int i, ret;
@@ -339,14 +417,13 @@
 		return -1;
 	}
 
-	output->compositor = ec;
+	memset(output, 0, sizeof *output);
+	wlsc_output_init(&output->base, &ec->base, 0, 0,
+			 mode->hdisplay, mode->vdisplay);
+
 	output->crtc_id = resources->crtcs[i];
 	output->connector_id = connector->connector_id;
 	output->mode = *mode;
-	output->x = 0;
-	output->y = 0;
-	output->width = mode->hdisplay;
-	output->height = mode->vdisplay;
 
 	drmModeFreeEncoder(encoder);
 
@@ -354,13 +431,17 @@
 	for (i = 0; i < 2; i++) {
 		glBindRenderbuffer(GL_RENDERBUFFER, output->rbo[i]);
 
-		attribs[1] = output->width;
-		attribs[3] = output->height;
-		output->image[i] = eglCreateDRMImageMESA(ec->display, attribs);
-		glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, output->image[i]);
-		eglExportDRMImageMESA(ec->display, output->image[i], NULL, &handle, &stride);
+		attribs[1] = output->base.width;
+		attribs[3] = output->base.height;
+		output->image[i] =
+			eglCreateDRMImageMESA(ec->base.display, attribs);
+		glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER,
+						       output->image[i]);
+		eglExportDRMImageMESA(ec->base.display, output->image[i],
+				      NULL, &handle, &stride);
 
-		ret = drmModeAddFB(ec->drm_fd, output->width, output->height,
+		ret = drmModeAddFB(ec->drm_fd,
+				   output->base.width, output->base.height,
 				   32, 32, stride, handle, &output->fb_id[i]);
 		if (ret) {
 			fprintf(stderr, "failed to add fb %d: %m\n", i);
@@ -381,13 +462,13 @@
 		return -1;
 	}
 
-	wl_list_insert(ec->output_list.prev, &output->link);
+	wl_list_insert(ec->base.output_list.prev, &output->base.link);
 
 	return 0;
 }
 
 static int
-create_outputs(struct wlsc_compositor *ec)
+create_outputs(struct drm_compositor *ec)
 {
 	drmModeConnector *connector;
 	drmModeRes *resources;
@@ -413,7 +494,7 @@
 		drmModeFreeConnector(connector);
 	}
 
-	if (wl_list_empty(&ec->output_list)) {
+	if (wl_list_empty(&ec->base.output_list)) {
 		fprintf(stderr, "No currently active connector found.\n");
 		return -1;
 	}
@@ -425,8 +506,8 @@
 
 static void on_enter_vt(int signal_number, void *data)
 {
-	struct wlsc_compositor *ec = data;
-	struct wlsc_output *output;
+	struct drm_compositor *ec = data;
+	struct drm_output *output;
 	int ret;
 
 	ret = drmSetMaster(ec->drm_fd);
@@ -441,19 +522,20 @@
 	ioctl(ec->tty_fd, VT_RELDISP, VT_ACKACQ);
 	ec->vt_active = 1;
 
-	wl_list_for_each(output, &ec->output_list, link) {
+	wl_list_for_each(output, &ec->base.output_list, base.link) {
 		ret = drmModeSetCrtc(ec->drm_fd, output->crtc_id,
 				     output->fb_id[output->current ^ 1], 0, 0,
 				     &output->connector_id, 1, &output->mode);
 		if (ret)
-			fprintf(stderr, "failed to set mode for connector %d: %m\n",
+			fprintf(stderr,
+				"failed to set mode for connector %d: %m\n",
 				output->connector_id);
 	}
 }
 
 static void on_leave_vt(int signal_number, void *data)
 {
-	struct wlsc_compositor *ec = data;
+	struct drm_compositor *ec = data;
 	int ret;
 
 	ret = drmDropMaster(ec->drm_fd);
@@ -470,7 +552,7 @@
 static void
 on_tty_input(int fd, uint32_t mask, void *data)
 {
-	struct wlsc_compositor *ec = data;
+	struct drm_compositor *ec = data;
 
 	/* Ignore input to tty.  We get keyboard events from evdev
 	 */
@@ -479,7 +561,7 @@
 
 static void on_term_signal(int signal_number, void *data)
 {
-	struct wlsc_compositor *ec = data;
+	struct drm_compositor *ec = data;
 
 	if (tcsetattr(ec->tty_fd, TCSANOW, &ec->terminal_attributes) < 0)
 		fprintf(stderr, "could not restore terminal to canonical mode\n");
@@ -487,7 +569,7 @@
 	exit(0);
 }
 
-static int setup_tty(struct wlsc_compositor *ec, struct wl_event_loop *loop)
+static int setup_tty(struct drm_compositor *ec, struct wl_event_loop *loop)
 {
 	struct termios raw_attributes;
 	struct vt_mode mode = { 0 };
@@ -536,59 +618,65 @@
 	return 0;
 }
 
-int
-wlsc_compositor_init_drm(struct wlsc_compositor *ec)
+struct wlsc_compositor *
+drm_compositor_create(struct wl_display *display)
 {
+	struct drm_compositor *ec;
 	struct udev_enumerate *e;
         struct udev_list_entry *entry;
 	struct udev_device *device;
 	const char *path;
-	struct wlsc_input_device *input_device;
 	struct wl_event_loop *loop;
 
+	ec = malloc(sizeof *ec);
+	if (ec == NULL)
+		return NULL;
+
+	memset(ec, 0, sizeof *ec);
 	ec->udev = udev_new();
 	if (ec->udev == NULL) {
 		fprintf(stderr, "failed to initialize udev context\n");
-		return -1;
+		return NULL;
 	}
 
-	input_device = wlsc_input_device_create(ec);
-	ec->input_device = input_device;
-
-	e = udev_enumerate_new(ec->udev);
-	udev_enumerate_add_match_subsystem(e, "input");
-	udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1");
-        udev_enumerate_scan_devices(e);
-        udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
-		path = udev_list_entry_get_name(entry);
-		device = udev_device_new_from_syspath(ec->udev, path);
-		evdev_input_device_create(input_device, ec->wl_display,
-					  udev_device_get_devnode(device));
-	}
-        udev_enumerate_unref(e);
-
 	e = udev_enumerate_new(ec->udev);
 	udev_enumerate_add_match_subsystem(e, "drm");
 	udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1");
         udev_enumerate_scan_devices(e);
+	device = NULL;
         udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
 		path = udev_list_entry_get_name(entry);
 		device = udev_device_new_from_syspath(ec->udev, path);
-		fprintf(stderr, "creating output for %s\n", path);
-
-		if (init_egl(ec, device) < 0) {
-			fprintf(stderr, "failed to initialize egl\n");
-			return -1;
-		}
-		if (create_outputs(ec) < 0) {
-			fprintf(stderr, "failed to create output for %s\n", path);
-			return -1;
-		}
+		break;
 	}
         udev_enumerate_unref(e);
 
-	loop = wl_display_get_event_loop(ec->wl_display);
-	setup_tty(ec, loop);
+	if (device == NULL) {
+		fprintf(stderr, "no drm device found\n");
+		return NULL;
+	}
 
-	return 0;
+	if (init_egl(ec, device) < 0) {
+		fprintf(stderr, "failed to initialize egl\n");
+		return NULL;
+	}
+	
+	/* Can't init base class until we have a current egl context */
+	wlsc_compositor_init(&ec->base, display);
+
+	if (create_outputs(ec) < 0) {
+		fprintf(stderr, "failed to create output for %s\n", path);
+		return NULL;
+	}
+
+	drm_input_create(ec);
+
+	loop = wl_display_get_event_loop(ec->base.wl_display);
+	ec->drm_source =
+		wl_event_loop_add_fd(loop, ec->drm_fd,
+				     WL_EVENT_READABLE, on_drm_input, ec);
+	setup_tty(ec, loop);
+	ec->base.present = drm_compositor_present;
+
+	return &ec->base;
 }