Add x11 backend for compositor
authorKristian Høgsberg <krh@bitplanet.net>
Mon, 14 Jun 2010 15:54:00 +0000 (11:54 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Mon, 14 Jun 2010 15:54:02 +0000 (11:54 -0400)
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.

Makefile
compositor-drm.c
compositor-x11.c [new file with mode: 0644]
compositor.c
compositor.h
configure.ac
event-loop.c

index ea41aa3..2ea2d3a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -28,6 +28,7 @@ $(libs) :
 compositor :                                   \
        compositor.o                            \
        compositor-drm.o                        \
+       compositor-x11.o                        \
        screenshooter.o                         \
        cairo-util.o
 
index 178941c..608ada9 100644 (file)
 #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 @@ struct evdev_input_device {
 
 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 @@ static void evdev_input_device_data(int fd, uint32_t mask, void *data)
                        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 @@ evdev_input_device_create(struct wlsc_input_device *master,
        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 @@ evdev_input_device_create(struct wlsc_input_device *master,
        return device;
 }
 
-void
-wlsc_compositor_present_drm(struct wlsc_compositor *ec)
+static void
+drm_input_create(struct drm_compositor *c)
+{
+       struct drm_input *input;
+       struct udev_enumerate *e;
+        struct udev_list_entry *entry;
+       struct udev_device *device;
+       const char *path;
+
+       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 wlsc_output *output;
+       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;
 
-       wl_list_for_each(output, &ec->output_list, link) {
-               drmModePageFlip(ec->drm_fd, output->crtc_id,
+               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 @@ on_drm_input(int fd, uint32_t mask, void *data)
 }
 
 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 @@ init_egl(struct wlsc_compositor *ec, struct udev_device *device)
                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 @@ init_egl(struct wlsc_compositor *ec, struct udev_device *device)
                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 drmModeModeInfo builtin_1024x768 = {
 };
 
 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 @@ create_output_for_connector(struct wlsc_compositor *ec,
                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 @@ create_output_for_connector(struct wlsc_compositor *ec,
        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);
-
-               ret = drmModeAddFB(ec->drm_fd, output->width, output->height,
+               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->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 @@ create_output_for_connector(struct wlsc_compositor *ec,
                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 @@ create_outputs(struct wlsc_compositor *ec)
                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 @@ create_outputs(struct wlsc_compositor *ec)
 
 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 @@ static void on_enter_vt(int signal_number, void *data)
        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_leave_vt(int signal_number, void *data)
 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 @@ on_tty_input(int fd, uint32_t mask, void *data)
 
 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 @@ static void on_term_signal(int signal_number, void *data)
        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 @@ static int setup_tty(struct wlsc_compositor *ec, struct wl_event_loop *loop)
        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_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);
-               evdev_input_device_create(input_device, ec->wl_display,
-                                         udev_device_get_devnode(device));
+               break;
        }
         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);
-        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 (device == NULL) {
+               fprintf(stderr, "no drm device found\n");
+               return NULL;
+       }
 
-               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;
-               }
+       if (init_egl(ec, device) < 0) {
+               fprintf(stderr, "failed to initialize egl\n");
+               return NULL;
        }
-        udev_enumerate_unref(e);
+       
+       /* 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->wl_display);
+       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 0;
+       return &ec->base;
 }
diff --git a/compositor-x11.c b/compositor-x11.c
new file mode 100644 (file)
index 0000000..82fecc8
--- /dev/null
@@ -0,0 +1,666 @@
+/*
+ * Copyright © 2008-2010 Kristian Høgsberg
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/time.h>
+
+#include <xcb/xcb.h>
+#include <xcb/dri2.h>
+#include <xcb/xfixes.h>
+
+#define GL_GLEXT_PROTOTYPES
+#define EGL_EGLEXT_PROTOTYPES
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "wayland.h"
+#include "wayland-protocol.h"
+#include "compositor.h"
+
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
+
+struct x11_compositor {
+       struct wlsc_compositor   base;
+
+       xcb_connection_t        *conn;
+       xcb_screen_t            *screen;
+       xcb_cursor_t             null_cursor;
+       int                      dri2_major;
+       int                      dri2_minor;
+       int                      drm_fd;
+       struct wl_event_source  *xcb_source;
+       struct {
+               xcb_atom_t               wm_protocols;
+               xcb_atom_t               wm_normal_hints;
+               xcb_atom_t               wm_size_hints;
+               xcb_atom_t               wm_delete_window;
+               xcb_atom_t               net_wm_name;
+               xcb_atom_t               utf8_string;
+       } atom;
+};
+
+struct x11_output {
+       struct wlsc_output      base;
+
+       xcb_xfixes_region_t     region;
+       xcb_window_t            window;
+       GLuint                  rbo;
+       EGLImageKHR             image;
+       xcb_rectangle_t         damage[16];
+       int                     damage_count;
+};
+
+struct x11_input {
+       struct wlsc_input_device base;
+};
+
+
+static void
+x11_input_create(struct x11_compositor *c)
+{
+       struct x11_input *input;
+
+       input = malloc(sizeof *input);
+       if (input == NULL)
+               return;
+
+       memset(input, 0, sizeof *input);
+       wlsc_input_device_init(&input->base, &c->base);
+
+       c->base.input_device = &input->base;
+}
+
+
+static int
+dri2_connect(struct x11_compositor *c)
+{
+       xcb_xfixes_query_version_reply_t *xfixes_query;
+       xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
+       xcb_dri2_query_version_reply_t *dri2_query;
+       xcb_dri2_query_version_cookie_t dri2_query_cookie;
+       xcb_dri2_connect_reply_t *connect;
+       xcb_dri2_connect_cookie_t connect_cookie;
+       xcb_generic_error_t *error;
+
+       xcb_prefetch_extension_data (c->conn, &xcb_xfixes_id);
+       xcb_prefetch_extension_data (c->conn, &xcb_dri2_id);
+
+       xfixes_query_cookie =
+               xcb_xfixes_query_version(c->conn,
+                                        XCB_XFIXES_MAJOR_VERSION,
+                                        XCB_XFIXES_MINOR_VERSION);
+   
+       dri2_query_cookie =
+               xcb_dri2_query_version (c->conn,
+                                       XCB_DRI2_MAJOR_VERSION,
+                                       XCB_DRI2_MINOR_VERSION);
+
+       connect_cookie = xcb_dri2_connect_unchecked (c->conn,
+                                                    c->screen->root,
+                                                    XCB_DRI2_DRIVER_TYPE_DRI);
+   
+       xfixes_query =
+               xcb_xfixes_query_version_reply (c->conn,
+                                               xfixes_query_cookie, &error);
+       if (xfixes_query == NULL ||
+           error != NULL || xfixes_query->major_version < 2) {
+               free(error);
+               return -1;
+       }
+       free(xfixes_query);
+
+       dri2_query =
+               xcb_dri2_query_version_reply (c->conn,
+                                             dri2_query_cookie, &error);
+       if (dri2_query == NULL || error != NULL) {
+               fprintf(stderr, "DRI2: failed to query version");
+               free(error);
+               return EGL_FALSE;
+       }
+       c->dri2_major = dri2_query->major_version;
+       c->dri2_minor = dri2_query->minor_version;
+       free(dri2_query);
+
+       connect = xcb_dri2_connect_reply (c->conn,
+                                         connect_cookie, NULL);
+       if (connect == NULL ||
+           connect->driver_name_length + connect->device_name_length == 0) {
+               fprintf(stderr, "DRI2: failed to authenticate");
+               return -1;
+       }
+
+       c->base.base.device =
+               strndup(xcb_dri2_connect_device_name (connect),
+                       xcb_dri2_connect_device_name_length (connect));
+                  
+       if (c->base.base.device == NULL) {
+               free(connect);
+               return -1;
+       }
+       free(connect);
+
+       return 0;
+}
+
+static int
+dri2_authenticate(struct x11_compositor *c)
+{
+       xcb_dri2_authenticate_reply_t *authenticate;
+       xcb_dri2_authenticate_cookie_t authenticate_cookie;
+       drm_magic_t magic;
+
+       if (drmGetMagic(c->drm_fd, &magic)) {
+               fprintf(stderr, "DRI2: failed to get drm magic");
+               return -1;
+       }
+
+       authenticate_cookie =
+               xcb_dri2_authenticate_unchecked(c->conn,
+                                               c->screen->root, magic);
+       authenticate =
+               xcb_dri2_authenticate_reply(c->conn,
+                                           authenticate_cookie, NULL);
+       if (authenticate == NULL || !authenticate->authenticated) {
+               fprintf(stderr, "DRI2: failed to authenticate");
+               free(authenticate);
+               return -1;
+       }
+
+       free(authenticate);
+
+       return 0;
+}
+
+static int
+x11_compositor_init_egl(struct x11_compositor *c)
+{
+       PFNEGLGETTYPEDDISPLAYMESA get_typed_display_mesa;
+       EGLint major, minor, count;
+       EGLConfig config;
+
+       static const EGLint config_attribs[] = {
+               EGL_SURFACE_TYPE,               0,
+               EGL_NO_SURFACE_CAPABLE_MESA,    EGL_OPENGL_BIT,
+               EGL_RENDERABLE_TYPE,            EGL_OPENGL_BIT,
+               EGL_NONE
+       };
+
+       if (dri2_connect(c) < 0)
+               return -1;
+       
+       c->drm_fd = open(c->base.base.device, O_RDWR);
+       if (c->drm_fd == -1) {
+               fprintf(stderr,
+                       "DRI2: could not open %s (%s)", c->base.base.device,
+                       strerror(errno));
+               return -1;
+       }
+
+       if (dri2_authenticate(c) < 0)
+               return -1;
+
+       get_typed_display_mesa =
+               (PFNEGLGETTYPEDDISPLAYMESA)
+               eglGetProcAddress("eglGetTypedDisplayMESA");
+       if (get_typed_display_mesa == NULL) {
+               fprintf(stderr, "eglGetTypedDisplayMESA() not found\n");
+               return -1;
+       }
+
+       c->base.display = get_typed_display_mesa(EGL_DRM_DISPLAY_TYPE_MESA,
+                                                (void *) c->drm_fd);
+       if (c->base.display == NULL) {
+               fprintf(stderr, "failed to create display\n");
+               return -1;
+       }
+
+       if (!eglInitialize(c->base.display, &major, &minor)) {
+               fprintf(stderr, "failed to initialize display\n");
+               return -1;
+       }
+
+       if (!eglChooseConfig(c->base.display,
+                            config_attribs, &config, 1, &count) ||
+           count == 0) {
+               fprintf(stderr, "eglChooseConfig() failed\n");
+               return -1;
+       }
+
+       eglBindAPI(EGL_OPENGL_API);
+       c->base.context = eglCreateContext(c->base.display,
+                                          config, EGL_NO_CONTEXT, NULL);
+       if (c->base.context == NULL) {
+               fprintf(stderr, "failed to create context\n");
+               return -1;
+       }
+
+       if (!eglMakeCurrent(c->base.display, EGL_NO_SURFACE,
+                           EGL_NO_SURFACE, c->base.context)) {
+               fprintf(stderr, "failed to make context current\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+static void
+x11_compositor_present(struct wlsc_compositor *base)
+{
+       struct x11_compositor *c = (struct x11_compositor *) base;
+       struct x11_output *output;
+       xcb_dri2_copy_region_cookie_t cookie;
+       struct timeval tv;
+       uint32_t msec;
+
+       glFlush();
+
+       wl_list_for_each(output, &c->base.output_list, base.link) {
+               cookie = xcb_dri2_copy_region_unchecked(c->conn,
+                                                       output->window,
+                                                       output->region,
+                                                       XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT,
+                                                       XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT);
+               free(xcb_dri2_copy_region_reply(c->conn, cookie, NULL));
+       }       
+
+       gettimeofday(&tv, NULL);
+       msec = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+       wlsc_compositor_finish_frame(&c->base, msec);
+}
+
+static void
+x11_output_set_wm_protocols(struct x11_output *output)
+{
+       xcb_atom_t list[1];
+       struct x11_compositor *c =
+               (struct x11_compositor *) output->base.compositor;
+
+       list[0] = c->atom.wm_delete_window;
+       xcb_change_property (c->conn, 
+                            XCB_PROP_MODE_REPLACE,
+                            output->window,
+                            c->atom.wm_protocols,
+                            XCB_ATOM_ATOM,
+                            32,
+                            ARRAY_SIZE(list),
+                            list);
+}
+
+struct wm_normal_hints {
+       uint32_t flags;
+       uint32_t pad[4];
+       int32_t min_width, min_height;
+       int32_t max_width, max_height;
+       int32_t width_inc, height_inc;
+       int32_t min_aspect_x, min_aspect_y;
+       int32_t max_aspect_x, max_aspect_y;
+       int32_t base_width, base_height;
+       int32_t win_gravity;
+};
+
+#define WM_NORMAL_HINTS_MIN_SIZE       16
+#define WM_NORMAL_HINTS_MAX_SIZE       32
+
+static int
+x11_compositor_create_output(struct x11_compositor *c, int width, int height)
+{
+       static const char name[] = "Wayland Compositor";
+       struct x11_output *output;
+       xcb_dri2_dri2_buffer_t *buffers;
+       xcb_dri2_get_buffers_reply_t *reply;
+       xcb_dri2_get_buffers_cookie_t cookie;
+       xcb_screen_iterator_t iter;
+       xcb_rectangle_t rectangle;
+       struct wm_normal_hints normal_hints;
+       unsigned int attachments[] =
+               { XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT};
+       uint32_t mask = XCB_CW_EVENT_MASK | XCB_CW_CURSOR;
+       uint32_t values[2] = { 
+               XCB_EVENT_MASK_KEY_PRESS |
+               XCB_EVENT_MASK_KEY_RELEASE |
+               XCB_EVENT_MASK_BUTTON_PRESS |
+               XCB_EVENT_MASK_BUTTON_RELEASE |
+               XCB_EVENT_MASK_POINTER_MOTION |
+               XCB_EVENT_MASK_EXPOSURE |
+               XCB_EVENT_MASK_STRUCTURE_NOTIFY,
+               0
+       };
+
+       EGLint attribs[] = {
+               EGL_WIDTH,              0,
+               EGL_HEIGHT,             0,
+               EGL_IMAGE_STRIDE_MESA,  0,
+               EGL_IMAGE_FORMAT_MESA,  EGL_IMAGE_FORMAT_ARGB8888_MESA,
+               EGL_NONE
+       };
+
+       output = malloc(sizeof *output);
+       if (output == NULL)
+               return -1;
+
+       memset(output, 0, sizeof *output);
+       wlsc_output_init(&output->base, &c->base, 0, 0, width, height);
+
+       values[1] = c->null_cursor;
+       output->window = xcb_generate_id(c->conn);
+       iter = xcb_setup_roots_iterator(xcb_get_setup(c->conn));
+       xcb_create_window(c->conn,
+                         XCB_COPY_FROM_PARENT,
+                         output->window,
+                         iter.data->root,
+                         0, 0,
+                         width, height,
+                         0,
+                         XCB_WINDOW_CLASS_INPUT_OUTPUT,
+                         iter.data->root_visual,
+                         mask, values);
+
+       /* Don't resize me. */
+       memset(&normal_hints, 0, sizeof normal_hints);
+       normal_hints.flags =
+               WM_NORMAL_HINTS_MAX_SIZE | WM_NORMAL_HINTS_MIN_SIZE;
+       normal_hints.min_width = width;
+       normal_hints.min_height = height;
+       normal_hints.max_width = width;
+       normal_hints.max_height = height;
+       xcb_change_property (c->conn, XCB_PROP_MODE_REPLACE, output->window,
+                            c->atom.wm_normal_hints,
+                            c->atom.wm_size_hints, 32,
+                            sizeof normal_hints / 4,
+                            (uint8_t *) &normal_hints);
+
+        xcb_map_window(c->conn, output->window);
+
+       /* Set window name.  Don't bother with non-EWMH WMs. */
+       xcb_change_property(c->conn, XCB_PROP_MODE_REPLACE, output->window,
+                           c->atom.net_wm_name, c->atom.utf8_string, 8,
+                           strlen(name), name);
+
+       rectangle.x = 0;
+       rectangle.y = 0;
+       rectangle.width = width;
+       rectangle.height = height;
+       output->region = xcb_generate_id(c->conn);
+       xcb_xfixes_create_region(c->conn, output->region, 1, &rectangle);
+
+       xcb_dri2_create_drawable (c->conn, output->window);
+
+       x11_output_set_wm_protocols(output);
+
+       cookie = xcb_dri2_get_buffers_unchecked (c->conn,
+                                                output->window,
+                                                1, 1, attachments);
+       reply = xcb_dri2_get_buffers_reply (c->conn, cookie, NULL);
+       if (reply == NULL)
+               return -1;
+       buffers = xcb_dri2_get_buffers_buffers (reply);
+       if (buffers == NULL)
+               return -1;
+
+       if (reply->count != 1) {
+               fprintf(stderr,
+                       "got wrong number of buffers (%d)\n", reply->count);
+               return -1;
+       }
+
+       attribs[1] = reply->width;
+       attribs[3] = reply->height;
+       attribs[5] = buffers[0].pitch / 4;
+       free(reply);
+
+       output->image =
+               eglCreateImageKHR(c->base.display, c->base.context,
+                                 EGL_DRM_IMAGE_MESA,
+                                 (EGLClientBuffer) buffers[0].name,
+                                 attribs);
+
+       glGenRenderbuffers(1, &output->rbo);
+       glBindRenderbuffer(GL_RENDERBUFFER, output->rbo);
+
+       glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER,
+                                              output->image);
+
+       glFramebufferRenderbuffer(GL_FRAMEBUFFER,
+                                 GL_COLOR_ATTACHMENT0,
+                                 GL_RENDERBUFFER,
+                                 output->rbo);
+
+       wl_list_insert(c->base.output_list.prev, &output->base.link);
+
+       return 0;
+}
+
+static void
+idle_repaint(void *data)
+{
+       struct x11_output *output = data;
+       struct x11_compositor *c =
+               (struct x11_compositor *) output->base.compositor;
+       xcb_xfixes_region_t region;
+       xcb_dri2_copy_region_cookie_t cookie;
+       
+       if (output->damage_count <= ARRAY_SIZE(output->damage)) {
+               region = xcb_generate_id(c->conn);
+               xcb_xfixes_create_region(c->conn, region,
+                                        output->damage_count, output->damage);
+       } else {
+               region = output->region;
+       }
+
+       cookie = xcb_dri2_copy_region_unchecked(c->conn,
+                                               output->window,
+                                               region,
+                                               XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT,
+                                               XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT);
+
+       if (region != output->region)
+               xcb_xfixes_destroy_region(c->conn, region);
+
+       free(xcb_dri2_copy_region_reply(c->conn, cookie, NULL));
+       output->damage_count = 0;
+}
+
+static struct x11_output *
+x11_compositor_find_output(struct x11_compositor *c, xcb_window_t window)
+{
+       struct x11_output *output;
+
+       wl_list_for_each(output, &c->base.output_list, base.link) {
+               if (output->window == window)
+                       return output;
+       }
+
+       return NULL;
+}
+
+static void
+x11_compositor_handle_event(int fd, uint32_t mask, void *data)
+{
+       struct x11_compositor *c = data;
+       struct x11_output *output;
+        xcb_generic_event_t *event;
+       struct wl_event_loop *loop;
+       xcb_client_message_event_t *client_message;
+       xcb_motion_notify_event_t *motion_notify;
+       xcb_key_press_event_t *key_press;
+       xcb_button_press_event_t *button_press;
+       xcb_expose_event_t *expose;
+       xcb_rectangle_t *r;
+       xcb_atom_t atom;
+
+       loop = wl_display_get_event_loop(c->base.wl_display);
+        while (event = xcb_poll_for_event (c->conn), event != NULL) {
+               switch (event->response_type & ~0x80) {
+
+               case XCB_KEY_PRESS:
+                       key_press = (xcb_key_press_event_t *) event;
+                       notify_key(c->base.input_device,
+                                  key_press->detail, 1);
+
+                       fprintf(stderr, "code %d, sequence %d\n",
+                               key_press->detail, key_press->sequence);
+
+                       break;
+               case XCB_KEY_RELEASE:
+                       key_press = (xcb_key_press_event_t *) event;
+                       notify_key(c->base.input_device,
+                                  key_press->detail, 0);
+                       break;
+               case XCB_BUTTON_PRESS:
+                       button_press = (xcb_button_press_event_t *) event;
+                       notify_button(c->base.input_device,
+                                     button_press->detail, 1);
+                       break;
+               case XCB_BUTTON_RELEASE:
+                       button_press = (xcb_button_press_event_t *) event;
+                       notify_button(c->base.input_device,
+                                     button_press->detail, 0);
+                       break;
+
+               case XCB_MOTION_NOTIFY:
+                       motion_notify = (xcb_motion_notify_event_t *) event;
+                       notify_motion(c->base.input_device,
+                                     motion_notify->event_x,
+                                     motion_notify->event_y);
+                       break;
+
+               case XCB_EXPOSE:
+                       expose = (xcb_expose_event_t *) event;
+                       output = x11_compositor_find_output(c, expose->window);
+                       if (output->damage_count == 0)
+                               wl_event_loop_add_idle(loop,
+                                                      idle_repaint, output);
+
+                       r = &output->damage[output->damage_count++];
+                       if (output->damage_count > 16)
+                               break;
+                       r->x = expose->x;
+                       r->y = expose->y;
+                       r->width = expose->width;
+                       r->height = expose->height;
+                       break;
+               case XCB_CLIENT_MESSAGE:
+                       client_message = (xcb_client_message_event_t *) event;
+                       atom = client_message->data.data32[0];
+                       if (atom == c->atom.wm_delete_window)
+                               exit(1);
+                       break;
+               default: 
+
+                       break;
+               }
+
+               free (event);
+        }
+}
+
+#define F(field) offsetof(struct x11_compositor, field)
+
+static void
+x11_compositor_get_resources(struct x11_compositor *c)
+{
+       static const struct { const char *name; int offset; } atoms[] = {
+               { "WM_PROTOCOLS",       F(atom.wm_protocols) },
+               { "WM_NORMAL_HINTS",    F(atom.wm_normal_hints) },
+               { "WM_SIZE_HINTS",      F(atom.wm_size_hints) },
+               { "WM_DELETE_WINDOW",   F(atom.wm_delete_window) },
+               { "_NET_WM_NAME",       F(atom.net_wm_name) },
+               { "UTF8_STRING",        F(atom.utf8_string) },
+       };
+
+       xcb_intern_atom_cookie_t cookies[ARRAY_SIZE(atoms)];
+       xcb_intern_atom_reply_t *reply;
+       xcb_pixmap_t pixmap;
+       xcb_gc_t gc;
+       int i;
+       uint8_t data[] = { 0, 0, 0, 0 };
+
+       for (i = 0; i < ARRAY_SIZE(atoms); i++)
+               cookies[i] = xcb_intern_atom (c->conn, 0,
+                                             strlen(atoms[i].name),
+                                             atoms[i].name);
+
+       for (i = 0; i < ARRAY_SIZE(atoms); i++) {
+               reply = xcb_intern_atom_reply (c->conn, cookies[i], NULL);
+               *(xcb_atom_t *) ((char *) c + atoms[i].offset) = reply->atom;
+               free(reply);
+       }
+
+       pixmap = xcb_generate_id(c->conn);
+       gc = xcb_generate_id(c->conn);
+       xcb_create_pixmap(c->conn, 1, pixmap, c->screen->root, 1, 1);
+       xcb_create_gc(c->conn, gc, pixmap, 0, NULL);
+       xcb_put_image(c->conn, XCB_IMAGE_FORMAT_XY_PIXMAP,
+                     pixmap, gc, 1, 1, 0, 0, 0, 32, sizeof data, data);
+       c->null_cursor = xcb_generate_id(c->conn);
+       xcb_create_cursor (c->conn, c->null_cursor,
+                          pixmap, pixmap, 0, 0, 0,  0, 0, 0,  1, 1);
+       xcb_free_gc(c->conn, gc);
+       xcb_free_pixmap(c->conn, pixmap);
+}
+
+struct wlsc_compositor *
+x11_compositor_create(struct wl_display *display)
+{
+       struct x11_compositor *c;
+       struct wl_event_loop *loop;
+       xcb_screen_iterator_t s;
+
+       c = malloc(sizeof *c);
+       if (c == NULL)
+               return NULL;
+
+       memset(c, 0, sizeof *c);
+       c->conn = xcb_connect(0, 0);
+
+       if (xcb_connection_has_error(c->conn))
+               return NULL;
+
+       s = xcb_setup_roots_iterator(xcb_get_setup(c->conn));
+       c->screen = s.data;
+
+       x11_compositor_get_resources(c);
+
+       x11_compositor_init_egl(c);
+
+       /* Can't init base class until we have a current egl context */
+       wlsc_compositor_init(&c->base, display);
+
+       x11_compositor_create_output(c, 1024, 640);
+
+       x11_input_create(c);
+
+       loop = wl_display_get_event_loop(c->base.wl_display);
+
+       c->xcb_source =
+               wl_event_loop_add_fd(loop, xcb_get_file_descriptor(c->conn),
+                                    WL_EVENT_READABLE,
+                                    x11_compositor_handle_event, c);
+
+       c->base.present = x11_compositor_present;
+
+       return &c->base;
+}
index 204c8db..fad9b7b 100644 (file)
@@ -355,8 +355,6 @@ wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs)
                              compositor->current_frame, msecs);
 
        wl_event_source_timer_update(compositor->timer_source, 5);
-       compositor->repaint_on_timeout = 1;
-
        compositor->current_frame++;
 }
 
@@ -379,13 +377,6 @@ wlsc_output_repaint(struct wlsc_output *output)
 
        wl_list_for_each(eid, &ec->input_device_list, link)
                wlsc_surface_draw(eid->sprite, output);
-
-       output->current ^= 1;
-
-       glFramebufferRenderbuffer(GL_FRAMEBUFFER,
-                                 GL_COLOR_ATTACHMENT0,
-                                 GL_RENDERBUFFER,
-                                 output->rbo[output->current]);
 }
 
 static void
@@ -402,7 +393,7 @@ repaint(void *data)
        wl_list_for_each(output, &ec->output_list, link)
                wlsc_output_repaint(output);
 
-       wlsc_compositor_present_drm(ec);
+       ec->present(ec);
 
        ec->repaint_needed = 0;
 }
@@ -628,9 +619,6 @@ notify_motion(struct wlsc_input_device *device, int x, int y)
        const int hotspot_x = 16, hotspot_y = 16;
        int32_t sx, sy;
 
-       if (!ec->vt_active)
-               return;
-
        /* FIXME: We need some multi head love here. */
        output = container_of(ec->output_list.next, struct wlsc_output, link);
        if (x < output->x)
@@ -668,8 +656,7 @@ notify_button(struct wlsc_input_device *device,
        struct wlsc_compositor *compositor = device->ec;
        int32_t sx, sy;
 
-       if (!compositor->vt_active)
-               return;
+       fprintf(stderr, "notify button: button %d, state %d\n", button, state);
 
        surface = pick_surface(device, &sx, &sy);
        if (surface) {
@@ -700,9 +687,6 @@ notify_key(struct wlsc_input_device *device,
        uint32_t *k, *end;
        uint32_t modifier;
 
-       if (!compositor->vt_active)
-               return;
-
        switch (key | compositor->modifier_state) {
        case KEY_BACKSPACE | MODIFIER_CTRL | MODIFIER_ALT:
                kill(0, SIGTERM);
@@ -769,16 +753,10 @@ handle_surface_destroy(struct wlsc_listener *listener,
        }
 }
 
-struct wlsc_input_device *
-wlsc_input_device_create(struct wlsc_compositor *ec)
+void
+wlsc_input_device_init(struct wlsc_input_device *device,
+                      struct wlsc_compositor *ec)
 {
-       struct wlsc_input_device *device;
-
-       device = malloc(sizeof *device);
-       if (device == NULL)
-               return NULL;
-
-       memset(device, 0, sizeof *device);
        device->base.interface = &wl_input_device_interface;
        device->base.implementation = NULL;
        wl_display_add_object(ec->wl_display, &device->base);
@@ -786,13 +764,12 @@ wlsc_input_device_create(struct wlsc_compositor *ec)
        device->x = 100;
        device->y = 100;
        device->ec = ec;
+       device->sprite = pointer_create(ec, device->x, device->y, 64, 64);
 
        device->listener.func = handle_surface_destroy;
        wl_list_insert(ec->surface_destroy_listener_list.prev,
                       &device->listener.link);
        wl_list_insert(ec->input_device_list.prev, &device->link);
-
-       return device;
 }
 
 static void
@@ -916,18 +893,37 @@ add_visuals(struct wlsc_compositor *ec)
        wl_display_add_global(ec->wl_display, &ec->rgb_visual.base, NULL);
 }
 
-static struct wlsc_compositor *
-wlsc_compositor_create(struct wl_display *display)
+void
+wlsc_output_init(struct wlsc_output *output, struct wlsc_compositor *c,
+                int x, int y, int width, int height)
 {
-       struct wlsc_compositor *ec;
-       struct wl_event_loop *loop;
-       struct wlsc_output *output;
+       output->compositor = c;
+       output->x = x;
+       output->y = y;
+       output->width = width;
+       output->height = height;
 
-       ec = malloc(sizeof *ec);
-       if (ec == NULL)
-               return NULL;
+       output->background =
+               background_create(output, option_background);
+
+       wlsc_matrix_init(&output->matrix);
+       wlsc_matrix_translate(&output->matrix,
+                             -output->x - output->width / 2.0,
+                             -output->y - output->height / 2.0, 0);
+       wlsc_matrix_scale(&output->matrix,
+                         2.0 / output->width, 2.0 / output->height, 1);
+
+       output->base.interface = &wl_output_interface;
+       wl_display_add_object(c->wl_display, &output->base);
+       wl_display_add_global(c->wl_display, &output->base,
+                             wlsc_output_post_geometry);
+}
+
+int
+wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display)
+{
+       struct wl_event_loop *loop;
 
-       memset(ec, 0, sizeof *ec);
        ec->wl_display = display;
 
        wl_display_set_compositor(display, &ec->base, &compositor_interface); 
@@ -941,34 +937,6 @@ wlsc_compositor_create(struct wl_display *display)
 
        screenshooter_create(ec);
 
-       if (wlsc_compositor_init_drm(ec) < 0) {
-               fprintf(stderr, "failed to initialize devices\n");
-               return NULL;
-       }
-
-       /* Create the pointer and background surfaces now that we have
-        * a current EGL context. */
-       ec->input_device->sprite =
-               pointer_create(ec, 
-                              ec->input_device->x,
-                              ec->input_device->y, 64, 64);
-       wl_list_for_each(output, &ec->output_list, link) {
-               output->background = background_create(output,
-                                                      option_background);
-
-               wlsc_matrix_init(&output->matrix);
-
-               wlsc_matrix_translate(&output->matrix,
-                                     -output->x - output->width / 2.0,
-                                     -output->y - output->height / 2.0, 0);
-               wlsc_matrix_scale(&output->matrix,
-                                 2.0 / output->width, 2.0 / output->height, 1);
-               output->base.interface = &wl_output_interface;
-               wl_display_add_object(ec->wl_display, &output->base);
-               wl_display_add_global(ec->wl_display, &output->base,
-                                     wlsc_output_post_geometry);
-       }
-
        glGenFramebuffers(1, &ec->fbo);
        glBindFramebuffer(GL_FRAMEBUFFER, ec->fbo);
        glActiveTexture(GL_TEXTURE0);
@@ -978,7 +946,7 @@ wlsc_compositor_create(struct wl_display *display)
        ec->timer_source = wl_event_loop_add_timer(loop, repaint, ec);
        wlsc_compositor_schedule_repaint(ec);
 
-       return ec;
+       return 0;
 }
 
 /* The plan here is to generate a random anonymous socket name and
@@ -1002,7 +970,11 @@ int main(int argc, char *argv[])
 
        display = wl_display_create();
 
-       ec = wlsc_compositor_create(display);
+       if (getenv("DISPLAY"))
+               ec = x11_compositor_create(display);
+       else
+               ec = drm_compositor_create(display);
+
        if (ec == NULL) {
                fprintf(stderr, "failed to create compositor\n");
                exit(EXIT_FAILURE);
index a4e42f0..99cce30 100644 (file)
@@ -54,15 +54,6 @@ struct wlsc_output {
        struct wlsc_surface *background;
        struct wlsc_matrix matrix;
        int32_t x, y, width, height;
-
-       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 wlsc_input_device {
@@ -87,7 +78,6 @@ struct wlsc_compositor {
 
        EGLDisplay display;
        EGLContext context;
-       int drm_fd;
        GLuint fbo, vbo;
        GLuint proj_uniform, tex_uniform;
        struct wl_display *wl_display;
@@ -101,28 +91,16 @@ struct wlsc_compositor {
 
        struct wl_list surface_destroy_listener_list;
 
-       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 udev *udev;
-
        /* Repaint state. */
        struct wl_event_source *timer_source;
        int repaint_needed;
        int repaint_on_timeout;
        struct timespec previous_swap;
        uint32_t current_frame;
-       struct wl_event_source *drm_source;
 
        uint32_t modifier_state;
+
+       void (*present)(struct wlsc_compositor *c);
 };
 
 #define MODIFIER_CTRL  (1 << 8)
@@ -152,14 +130,25 @@ void
 notify_key(struct wlsc_input_device *device, uint32_t key, uint32_t state);
 
 void
-wlsc_compositor_present_drm(struct wlsc_compositor *wlsc);
-int
-wlsc_compositor_init_drm(struct wlsc_compositor *ec);
-void
 wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs);
 struct wlsc_input_device *
 wlsc_input_device_create(struct wlsc_compositor *ec);
 
+int
+wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display);
+void
+wlsc_output_init(struct wlsc_output *output, struct wlsc_compositor *c,
+                int x, int y, int width, int height);
+void
+wlsc_input_device_init(struct wlsc_input_device *device,
+                      struct wlsc_compositor *ec);
+
+struct wlsc_compositor *
+x11_compositor_create(struct wl_display *display);
+
+struct wlsc_compositor *
+drm_compositor_create(struct wl_display *display);
+
 void
 screenshooter_create(struct wlsc_compositor *ec);
 
index 4040121..8097035 100644 (file)
@@ -5,7 +5,7 @@ PKG_PROG_PKG_CONFIG()
 PKG_CHECK_MODULES(FFI, [libffi])
 
 PKG_CHECK_MODULES(COMPOSITOR,
-                 [egl gl libpng cairo gdk-pixbuf-2.0 libudev >= 136 libdrm >= 2.4.17])
+                 [egl gl libpng cairo gdk-pixbuf-2.0 libudev >= 136 libdrm >= 2.4.17] xcb-dri2 xcb-xfixes)
 PKG_CHECK_MODULES(CLIENT, [egl gl cairo-gl gdk-pixbuf-2.0 glib-2.0 gobject-2.0])
 PKG_CHECK_MODULES(POPPLER, [poppler-glib gdk-2.0])
 
index f6252a8..8568f40 100644 (file)
@@ -342,6 +342,7 @@ wl_event_source_idle_remove(struct wl_event_source *source)
                (struct wl_event_source_idle *) source;
 
        wl_list_remove(&idle_source->link);
+       free(source);
 
        return 0;
 }