x11: update x11-backend module
authorjaehoon01.jeong <jaehoon01.jeong@samsung.com>
Wed, 22 Apr 2015 07:45:32 +0000 (16:45 +0900)
committerTaekyun Kim <tkq.kim@samsung.com>
Fri, 19 Jun 2015 09:06:40 +0000 (18:06 +0900)
    - renderer initialize
    - pixman rendering with xcb-shm
    - handle some x-events

Change-Id: Ib36902f6fe086c9018f89f20c891ee2b9ca3adda

src/modules/x11/pepper-x11.h
src/modules/x11/x11-common.c
src/modules/x11/x11-input.c
src/modules/x11/x11-internal.h
src/modules/x11/x11-output.c

index ff45c2373a9f4b3aadcc04741184dcad978563dc..771a6f1582be6cebcffb01159a5d898a8c630b42 100644 (file)
@@ -16,7 +16,8 @@ PEPPER_API void
 pepper_x11_destroy(pepper_x11_connection_t *conn);
 
 PEPPER_API pepper_output_t *
-pepper_x11_output_create(pepper_x11_connection_t *connection, int32_t w, int32_t h);
+pepper_x11_output_create(pepper_x11_connection_t *connection, int32_t w, int32_t h,
+                         const char *renderer);
 
 PEPPER_API void
 pepper_x11_seat_create(pepper_x11_connection_t* connection);
index 63b2477974333d54af46b570115137d4ff6be342..89511773f850b40294b1d630f5258a61b9f94462 100644 (file)
@@ -1,6 +1,7 @@
 #include <wayland-server.h>
 #include <common.h>
 #include "x11-internal.h"
+#include "pepper-internal.h"
 
 #include <stdlib.h>
 
  * xcb is faster than xlib
  */
 
+/* TODO: debugging */
+#undef  PEPPER_TRACE
+#define PEPPER_TRACE(x)
+
 static inline pepper_bool_t
 x11_get_next_event(xcb_connection_t *xcb_conn, xcb_generic_event_t **event, uint32_t mask)
 {
@@ -20,6 +25,20 @@ x11_get_next_event(xcb_connection_t *xcb_conn, xcb_generic_event_t **event, uint
     return *event != NULL;
 }
 
+static x11_output_t *
+x11_find_output_by_window(pepper_x11_connection_t *conn, xcb_window_t window)
+{
+    x11_output_t *output = NULL;
+
+    if (!wl_list_empty(&conn->outputs))
+    {
+        wl_list_for_each(output, &conn->outputs, link)
+            if ( window == output->window )
+                return output;
+    }
+    return NULL;
+}
+
 static int
 x11_handle_event(int fd, uint32_t mask, void *data)
 {
@@ -29,9 +48,6 @@ x11_handle_event(int fd, uint32_t mask, void *data)
 
     uint32_t                    count = 0;
 
-    if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR))
-        return 0;
-
     if (!connection->use_xinput)
         return 0;
 
@@ -43,6 +59,7 @@ x11_handle_event(int fd, uint32_t mask, void *data)
     while(x11_get_next_event(connection->xcb_connection, &event, mask))
     {
         uint32_t type = event->response_type & ~0x80;
+
         switch (type)
         {
         case XCB_ENTER_NOTIFY:
@@ -55,10 +72,59 @@ x11_handle_event(int fd, uint32_t mask, void *data)
             x11_handle_input_event(seat, type, event);
             break;
         case XCB_EXPOSE:
-            /*PEPPER_ERROR("x11:event:not input event\n");*/
+            PEPPER_TRACE("XCB_EXPOSE\n");
+            {
+                xcb_expose_event_t *expose = (xcb_expose_event_t *)event;
+                x11_output_t *output = x11_find_output_by_window(connection, expose->window);
+                if (output)
+                    pepper_output_schedule_repaint(output->base);
+            }
+            break;
+        case XCB_FOCUS_IN:
+            /* TODO: Cursor handling */
+            PEPPER_TRACE("XCB_FOCUS_IN\n");
+            break;
+        case XCB_FOCUS_OUT:
+            PEPPER_TRACE("XCB_FOCUS_OUT\n");
+            break;
+        case XCB_KEYMAP_NOTIFY:
+            PEPPER_TRACE("XCB_KEYMAP_NOTIFY\n");
+            break;
+        case XCB_CONFIGURE_NOTIFY:
+            /* Window moved */
+            PEPPER_TRACE("XCB_CONFIGURE_NOTIFY\n");
+            break;
+        case XCB_QUERY_EXTENSION:
+            PEPPER_TRACE("XCB_QUERY_EXTENSION\n");
+            break;
+        case XCB_DESTROY_NOTIFY:
+            PEPPER_TRACE("XCB_DESTROY_NOTIFY\n");
+            break;
+        case XCB_UNMAP_NOTIFY:
+            PEPPER_TRACE("XCB_UNMAP_NOTIFY\n");
+            break;
+        case XCB_CLIENT_MESSAGE:
+            PEPPER_TRACE("XCB_CLIENT_MESSAGE\n");
+            {
+                xcb_client_message_event_t *msg;
+                xcb_atom_t                  atom;
+                xcb_window_t                window;
+                x11_output_t               *output = NULL;
+
+                msg = (xcb_client_message_event_t *)event;
+                atom = msg->data.data32[0];
+                window = msg->window;
+
+                if (atom == connection->atom.wm_delete_window)
+                {
+                    output = x11_find_output_by_window(connection, window);
+                    if (output)
+                        x11_output_destroy(output);
+                }
+            }
             break;
         default :
-            PEPPER_ERROR("x11:common:Unknown event\n");
+            PEPPER_ERROR("unknown event: type [0x%x] \n", type);
             break;
         }
 
@@ -125,21 +191,21 @@ pepper_x11_connect(pepper_compositor_t *compositor, const char *display_name)
 
     if (!compositor)
     {
-        PEPPER_ERROR("x11:common:%s: compositor is null\n", __FUNCTION__);
+        PEPPER_ERROR("Compositor is null\n");
         return NULL;
     }
 
     connection = (pepper_x11_connection_t *)pepper_calloc(1, sizeof(pepper_x11_connection_t));
     if (!connection)
     {
-        PEPPER_ERROR("x11:common:%s: memory allocation failed\n", __FUNCTION__);
+        PEPPER_ERROR("Memory allocation failed\n");
         return NULL;
     }
 
     connection->display = XOpenDisplay(display_name);
     if (!connection->display)
     {
-        PEPPER_ERROR("x11:common:%s: XOpenDisplay failed\n", __FUNCTION__);
+        PEPPER_ERROR("XOpenDisplay failed\n");
         pepper_free(connection);
         return NULL;
     }
@@ -149,7 +215,7 @@ pepper_x11_connect(pepper_compositor_t *compositor, const char *display_name)
 
     if (xcb_connection_has_error(connection->xcb_connection))
     {
-        PEPPER_ERROR("x11:common:%s: xcb connection has error\n", __FUNCTION__);
+        PEPPER_ERROR("xcb connection has error\n");
         pepper_free(connection);
         return NULL;
     }
index 62c6c64ccb732bb9394201cd06ed2aa9ee906f9b..8f236f7a03d4c1c36afd2ff3b54b05110d4e51f3 100644 (file)
@@ -1,16 +1,26 @@
 #include "x11-internal.h"
 
+/* TODO: debugging */
+#undef  PEPPER_TRACE
+#define PEPPER_TRACE(x)
+
 void
 x11_handle_input_event(x11_seat_t* seat, uint32_t type, xcb_generic_event_t* xev)
 {
-    pepper_input_event_t        event;
-
-    memset(&event, 0x00, sizeof(pepper_input_event_t));
+    pepper_input_event_t event = {0,};
 
     switch (type)
     {
     case XCB_ENTER_NOTIFY:
+        {
+            PEPPER_TRACE("enter\n");
+            break;
+        }
     case XCB_LEAVE_NOTIFY:
+        {
+            PEPPER_TRACE("leave\n");
+            break;
+        }
     case XCB_KEY_PRESS:
     case XCB_KEY_RELEASE:
         break;
@@ -20,15 +30,15 @@ x11_handle_input_event(x11_seat_t* seat, uint32_t type, xcb_generic_event_t* xev
             switch (bp->detail)
             {
             case XCB_BUTTON_INDEX_1:/* FIXME: LEFT */
-                PEPPER_ERROR("left click\n");
+                PEPPER_TRACE("left click\n");
                 event.index = 1;
                 break;
             case XCB_BUTTON_INDEX_3:/* FIXME: RIGHT */
-                PEPPER_ERROR("right click\n");
+                PEPPER_TRACE("right click\n");
                 event.index = 3;
                 break;
             default:
-                PEPPER_ERROR("wheel or something pressed\n");
+                PEPPER_TRACE("wheel or something pressed\n");
                 break;
             }
             event.type   = PEPPER_INPUT_EVENT_POINTER_BUTTON;
@@ -46,15 +56,15 @@ x11_handle_input_event(x11_seat_t* seat, uint32_t type, xcb_generic_event_t* xev
             switch (br->detail)
             {
             case XCB_BUTTON_INDEX_1:/* FIXME: LEFT */
-                PEPPER_ERROR("left released\n");
+                PEPPER_TRACE("left released\n");
                 event.index = 1;
                 break;
             case XCB_BUTTON_INDEX_3:/* FIXME: RIGHT */
-                PEPPER_ERROR("right released\n");
+                PEPPER_TRACE("right released\n");
                 event.index = 3;
                 break;
             default:
-                PEPPER_ERROR("wheel or something pressed\n");
+                PEPPER_TRACE("wheel or something pressed\n");
                 break;
             }
             event.type   = PEPPER_INPUT_EVENT_POINTER_BUTTON;
@@ -69,6 +79,7 @@ x11_handle_input_event(x11_seat_t* seat, uint32_t type, xcb_generic_event_t* xev
     case XCB_MOTION_NOTIFY:
         {
             xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *)xev;
+
             event.type   = PEPPER_INPUT_EVENT_POINTER_MOTION;
             event.time   = motion->time;
             event.serial = motion->sequence;
@@ -80,7 +91,7 @@ x11_handle_input_event(x11_seat_t* seat, uint32_t type, xcb_generic_event_t* xev
         }
         break;
     default :
-        PEPPER_ERROR("x11:input: unknown input event\n");
+        PEPPER_ERROR("unknown input event, [0x%x]\n", type);
     }
 
     pepper_seat_handle_event(seat->base, &event);
@@ -157,16 +168,14 @@ pepper_x11_seat_create(pepper_x11_connection_t* conn)
 
     if (!conn)
     {
-        PEPPER_ERROR("x11:input:%s: connection is null...\n", __FUNCTION__);
+        PEPPER_ERROR("connection is null...\n");
         return ;
     }
 
-    PEPPER_ERROR("x11:input: initialize input module...\n");
-
     seat = pepper_calloc(1, sizeof(x11_seat_t));
     if (!seat)
     {
-        PEPPER_ERROR("x11:input:%s: failed to allocate memory\n", __FUNCTION__);
+        PEPPER_ERROR("failed to allocate memory\n");
         return ;
     }
 
index a330b7ccb2bf576a5bb5284324f0febfc85a6a52..ea7d1edd6d618799640ab87ede0072154b8f5d25 100644 (file)
@@ -9,51 +9,70 @@
 #include <X11/Xlib.h>
 #include <X11/Xlib-xcb.h>
 #include <string.h>
+#include <pixman.h>
 
-#define X11_BACKEND_INPUT_ID 0x12345678
+#define X11_BACKEND_INPUT_ID    0x12345678
 
-typedef struct x11_output   x11_output_t;
-typedef struct x11_cursor   x11_cursor_t;
-typedef struct x11_seat     x11_seat_t;
+typedef struct x11_output       x11_output_t;
+typedef struct x11_cursor       x11_cursor_t;
+typedef struct x11_seat         x11_seat_t;
+typedef struct x11_shm_image    x11_shm_image_t;
+
+struct x11_shm_image
+{
+    int              shm_id;
+    void            *buf;
+    xcb_shm_seg_t    segment;
+    pixman_image_t  *image;    /* XXX: need double-buffering? */
+};
 
 struct x11_output
 {
-    pepper_x11_connection_t *connection;
+    pepper_output_t *base;
+    pepper_x11_connection_t     *connection;
+
+    int32_t                  x, y;
+    uint32_t                 w, h;
+    uint32_t                 subpixel;
+    uint32_t                 scale;
+    uint8_t                  depth;
+    uint8_t                  bpp;
 
-    int32_t             x, y;
-    uint32_t            w, h;
-    uint32_t            subpixel;
-    uint32_t            scale;
-    uint8_t             depth;
+    xcb_window_t             window;
+    xcb_gc_t                 gc;
+    x11_cursor_t            *cursor;
 
-    xcb_window_t        window;
-    xcb_gc_t            gc;
-    x11_cursor_t        *cursor;
+    x11_shm_image_t          shm;
 
-    struct wl_signal    destroy_signal;
-    struct wl_signal    mode_change_signal;
+    pepper_renderer_t       *renderer;
 
-    struct wl_listener  conn_destroy_listener;
+    struct wl_signal         destroy_signal;
+    struct wl_signal         mode_change_signal;
+    struct wl_signal         frame_signal;
 
-    struct wl_list      link;
+    struct wl_event_source  *frame_done_timer;
+
+    struct wl_listener       conn_destroy_listener;
+
+    struct wl_list           link;
 };
 
 struct x11_seat
 {
-    pepper_seat_t       *base;
+    pepper_seat_t           *base;
 
-    uint32_t            id;
-    uint32_t            caps;
-    char                *name;
+    uint32_t                 id;
+    uint32_t                 caps;
+    char                    *name;
 
-    wl_fixed_t          pointer_x_last;
-    wl_fixed_t          pointer_y_last;
-    wl_fixed_t          touch_x_last;   /* FIXME */
-    wl_fixed_t          touch_y_last;   /* FIXME */
+    wl_fixed_t               pointer_x_last;
+    wl_fixed_t               pointer_y_last;
+    wl_fixed_t               touch_x_last;   /* FIXME */
+    wl_fixed_t               touch_y_last;   /* FIXME */
 
-    struct wl_list      link;
-    struct wl_signal    capabilities_signal;
-    struct wl_signal    name_signal;
+    struct wl_list           link;
+    struct wl_signal         capabilities_signal;
+    struct wl_signal         name_signal;
 };
 
 struct pepper_x11_connection
@@ -72,7 +91,7 @@ struct pepper_x11_connection
     struct wl_list          outputs;
 
     pepper_bool_t           use_xinput;
-    x11_seat_t              *seat;
+    x11_seat_t             *seat;
 
     struct {
         xcb_atom_t          wm_protocols;
@@ -128,4 +147,7 @@ x11_window_input_property_change(xcb_connection_t *conn, xcb_window_t window);
 void
 x11_handle_input_event(x11_seat_t* seat, uint32_t type, xcb_generic_event_t* xev);
 
+void
+x11_output_destroy(void *o);
+
 #endif  /*X11_INTERNAL_H*/
index 7bbbbc30ce4446bf53e195222907ef36bc3fc119..f77c7862cbda8721dc6f5d812ad5a05c49b52f6b 100644 (file)
@@ -1,7 +1,15 @@
 #include "x11-internal.h"
 
+#include "pepper-gl-renderer.h"
+#include "pepper-pixman-renderer.h"
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
 static uint8_t
-x11_get_depth_of_visual(xcb_screen_t *screen, xcb_visualid_t id)
+xcb_depth_get(xcb_screen_t *screen, xcb_visualid_t id)
 {
     xcb_depth_iterator_t i;
     xcb_visualtype_iterator_t j;
@@ -19,15 +27,9 @@ x11_get_depth_of_visual(xcb_screen_t *screen, xcb_visualid_t id)
     return 0;
 }
 
-static void
-x11_output_visual_iterate(void *o)
+static xcb_visualtype_t *
+xcb_visualtype_get(xcb_screen_t *screen, xcb_visualid_t id)
 {
-    x11_output_t *output = o;
-
-    xcb_screen_t     *screen;
-    xcb_visualtype_t *visual_type = NULL;    /* the returned visual type */
-
-    screen = output->connection->screen;
     if (screen)
     {
         xcb_depth_iterator_t depth_iter;
@@ -39,23 +41,263 @@ x11_output_visual_iterate(void *o)
 
             visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
             for (; visual_iter.rem; xcb_visualtype_next(&visual_iter))
-            {
-                visual_type = visual_iter.data;
-                printf("visual %d, class: %d, bits per rgb value: %d, colormap_entries %d, r:%#010x, g:%#010x, b:%#010x, depth %d\n",
-                       visual_type->visual_id,
-                       visual_type->_class,
-                       visual_type->colormap_entries,
-                       visual_type->bits_per_rgb_value,
-                       visual_type->red_mask,
-                       visual_type->green_mask,
-                       visual_type->blue_mask,
-                       x11_get_depth_of_visual(screen, visual_type->visual_id));
-            }
+                if (visual_iter.data->visual_id == id)
+                    return visual_iter.data;
         }
     }
+    return NULL;
 }
 
 static void
+x11_output_wait_for_map(x11_output_t *output)
+{
+    xcb_generic_event_t     *event;
+    xcb_map_notify_event_t  *map_notify;
+
+    uint8_t response_type;
+    int     mapped = 0, configured = 0;
+
+    while (!mapped || !configured)
+    {
+        event = xcb_wait_for_event(output->connection->xcb_connection);
+        response_type = event->response_type & ~0x80;
+
+        switch (response_type)
+        {
+        case XCB_MAP_NOTIFY:
+            map_notify = (xcb_map_notify_event_t *) event;
+            if (map_notify->window == output->window)
+                mapped = 1;
+            break;
+        case XCB_CONFIGURE_NOTIFY:
+            configured = 1;
+            break;
+        }
+    }
+}
+
+static int
+frame_done_handler(void* data)
+{
+    x11_output_t *output = data;
+    wl_signal_emit(&output->frame_signal, NULL);
+
+    return 1;
+}
+
+static pepper_bool_t
+gl_renderer_init(x11_output_t *output)
+{
+    xcb_visualid_t visual = output->connection->screen->root_visual;
+
+    output->renderer = pepper_gl_renderer_create(output->connection->display,
+                                                 (void *)(uintptr_t)output->window,
+                                                 PEPPER_FORMAT_XRGB8888, /* FIXME: */
+                                                 &visual);
+    if (!output->renderer)
+    {
+        PEPPER_ERROR("gl_renderer_create failed\n");
+        return PEPPER_FALSE;
+    }
+
+    return PEPPER_TRUE;
+}
+
+static void
+x11_shm_image_deinit(xcb_connection_t *conn, x11_shm_image_t *shm)
+{
+    if (shm->image)
+    {
+        pixman_image_unref(shm->image);
+        shm->image = NULL;
+    }
+
+    if (shm->segment)
+    {
+        xcb_shm_detach(conn, shm->segment);
+        shm->segment = 0;
+    }
+
+    if (shm->buf)
+    {
+        shmdt(shm->buf);
+        shm->buf = NULL;
+    }
+
+    if (shm->shm_id)
+    {
+        shmctl(shm->shm_id, IPC_RMID, NULL);
+        shm->shm_id = -1;
+    }
+}
+
+static pepper_bool_t
+x11_shm_image_init(x11_shm_image_t *shm, xcb_connection_t *conn, int w, int h, int bpp)
+{
+    xcb_generic_error_t     *err = NULL;
+    xcb_void_cookie_t        cookie;
+    pixman_format_code_t     pixman_format;
+
+    /* FIXME: Hard coded */
+    if (bpp == 32)
+    {
+        pixman_format = PIXMAN_x8r8g8b8;
+    }
+    else if (bpp == 16)
+    {
+        pixman_format = PIXMAN_r5g6b5;
+    }
+    else
+    {
+        PEPPER_ERROR("cannot find pixman format\n");
+        goto err;
+    }
+
+    /* Create MIT-SHM id and attach */
+    shm->shm_id = shmget(IPC_PRIVATE, w * h * (bpp/ 8), IPC_CREAT | S_IRWXU);
+    if (shm->shm_id == -1)
+    {
+        PEPPER_ERROR("shmget() failed\n");
+        goto err;
+    }
+
+    shm->buf = shmat(shm->shm_id, NULL, 0 /* read/write */);
+    if (-1 == (long)shm->buf)
+    {
+        PEPPER_ERROR("shmat() failed\n");
+        goto err;
+    }
+
+    /* Create XCB-SHM segment and attach */
+    shm->segment = xcb_generate_id(conn);
+    cookie = xcb_shm_attach_checked(conn, shm->segment, shm->shm_id, 1);
+    err = xcb_request_check(conn, cookie);
+    if (err)
+    {
+        PEPPER_ERROR("xcb_shm_attach error %d\n", err->error_code);
+        goto err;
+    }
+
+    shmctl(shm->shm_id, IPC_RMID, NULL);
+
+    /* Now create pixman image */
+    shm->image = pixman_image_create_bits(pixman_format, w, h, shm->buf,
+                                          w * (bpp/ 8));
+    if (!shm->image)
+    {
+        PEPPER_ERROR("pixman_image_create failed\n");
+        goto err;
+    }
+
+    return PEPPER_TRUE;
+
+err:
+    if (err)
+        free(err);
+
+    if (shm->buf)
+       shmdt(shm->buf);
+
+    if (shm->shm_id)
+        shmctl(shm->shm_id, IPC_RMID, NULL);
+
+    return PEPPER_FALSE;
+}
+
+static pepper_bool_t
+x11_shm_init(x11_output_t *output)
+{
+    xcb_screen_iterator_t    scr_iter;
+    xcb_format_iterator_t    fmt_iter;
+    xcb_visualtype_t        *visual_type;
+    xcb_connection_t        *xcb_conn = output->connection->xcb_connection;
+    int bpp = 0;
+
+    /* Check if XCB-SHM is available */
+    {
+        const xcb_query_extension_reply_t   *ext;
+        ext = xcb_get_extension_data(xcb_conn, &xcb_shm_id);
+        if (ext == NULL || !ext->present)
+        {
+            PEPPER_ERROR("xcb-shm extension is not available\n");
+            return PEPPER_FALSE;
+        }
+    }
+
+    /* Find root visual */
+    scr_iter = xcb_setup_roots_iterator(xcb_get_setup(xcb_conn));
+    visual_type = xcb_visualtype_get(scr_iter.data,
+                                     scr_iter.data->root_visual);
+    if (!visual_type)
+    {
+        PEPPER_ERROR("Failed to lookup visual for root window\n");
+        return PEPPER_FALSE;;
+    }
+
+    output->depth = xcb_depth_get(scr_iter.data,
+                                  scr_iter.data->root_visual);
+    PEPPER_TRACE("Visual depth is %d\n", output->depth);
+
+    fmt_iter = xcb_setup_pixmap_formats_iterator(xcb_get_setup(xcb_conn));
+    for (; fmt_iter.rem; xcb_format_next(&fmt_iter))
+    {
+        if (fmt_iter.data->depth == output->depth)
+        {
+            bpp = fmt_iter.data->bits_per_pixel;
+            break;
+        }
+    }
+    output->bpp = bpp;
+    PEPPER_TRACE("Found format for depth %d, bpp: %d\n", output->depth, bpp);
+
+    /* Init x11_shm_image */
+    if (!x11_shm_image_init(&output->shm, xcb_conn, output->w, output->h, bpp))
+    {
+        PEPPER_ERROR("x11_shm_image_init failed\n");
+        return PEPPER_FALSE;
+    }
+
+    output->gc = xcb_generate_id(xcb_conn);
+    xcb_create_gc(xcb_conn, output->gc, output->window, 0, NULL);
+
+    return PEPPER_TRUE;
+}
+
+static pepper_bool_t
+pixman_renderer_init(x11_output_t *output)
+{
+    /* Initialize xcb-shm infra and init shm-buffer */
+    if (!x11_shm_init(output))
+    {
+        PEPPER_ERROR("shm_init failed\n");
+        return PEPPER_FALSE;
+    }
+
+    /* Create pixman renderer */
+    output->renderer = pepper_pixman_renderer_create();
+    if (!output->renderer)
+    {
+        PEPPER_ERROR("pixman_renderer_create failed\n");
+        return PEPPER_FALSE;
+    }
+
+    return PEPPER_TRUE;
+}
+
+static pepper_bool_t
+renderer_init(x11_output_t *output, const char *renderer)
+{
+    if (!strcmp(renderer, "gl"))
+    {
+        if (gl_renderer_init(output))
+            return PEPPER_TRUE;
+    }
+
+    /* Pixman is default renderer */
+    return pixman_renderer_init(output);
+}
+
+void
 x11_output_destroy(void *o)
 {
     x11_output_t            *output;
@@ -63,19 +305,26 @@ x11_output_destroy(void *o)
 
     if (!o)
     {
-        PEPPER_ERROR("x11:output:%s: output is null\n", __FUNCTION__);
+        PEPPER_ERROR("output is null\n");
         return ;
     }
 
     output = o;
     conn = output->connection;
 
-    wl_signal_emit(&output->destroy_signal, output);
+    /* XXX */
+    x11_shm_image_deinit(conn->xcb_connection, &output->shm);
+
+    wl_event_source_remove(output->frame_done_timer);
 
     xcb_destroy_window(conn->xcb_connection, output->window);
 
+    wl_signal_emit(&output->destroy_signal, output);
+
     wl_list_remove(&output->link);
 
+    xcb_flush(conn->xcb_connection);
+
     pepper_free(output);
 }
 
@@ -90,14 +339,14 @@ static const char *
 x11_output_get_maker_name(void *o)
 {
     PEPPER_IGNORE(o);
-    return "pepper_x11";
+    return "PePPer_x11";
 }
 
 static const char *
 x11_output_get_model_name(void *o)
 {
     PEPPER_IGNORE(o);
-    return "pepper_x11";
+    return "PePPer_x11";
 }
 
 static int
@@ -139,7 +388,52 @@ x11_output_set_mode(void *o, const pepper_output_mode_t *mode)
         output->w = mode->w;
         output->h = mode->h;
 
-        /* TODO: Handle resize here. */
+        /* Resize output window. */
+        {
+            xcb_connection_t *conn = output->connection->xcb_connection;
+            xcb_size_hints_t hints;
+            uint32_t values[2];
+
+            values[0] = output->w;
+            values[1] = output->h;
+
+            /* set hints for window */
+            memset(&hints, 0, sizeof(hints));
+            hints.flags = WM_NORMAL_HINTS_MAX_SIZE | WM_NORMAL_HINTS_MIN_SIZE;
+            hints.min_width  = hints.max_width  = output->w*output->scale;
+            hints.min_height = hints.max_height = output->h*output->scale;
+            xcb_change_property(conn,
+                                XCB_PROP_MODE_REPLACE,
+                                output->window,
+                                output->connection->atom.wm_normal_hints,
+                                output->connection->atom.wm_size_hints,
+                                32,
+                                sizeof(hints) / 4,
+                                (uint8_t *)&hints);
+
+            /* resize window */
+            xcb_configure_window (conn,
+                                  output->window,
+                                  XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
+                                  values);
+
+            /* resize pixman image */
+            if (output->shm.image)
+            {
+                /* Release existing shm-buffer and pixman-image */
+                x11_shm_image_deinit(conn, &output->shm);
+
+                /* Init x11_shm_image */
+                if (!x11_shm_image_init(&output->shm, conn, output->w, output->h, output->bpp))
+                {
+                    PEPPER_ERROR("x11_shm_image_init failed\n");
+                    return PEPPER_FALSE;
+                }
+            }
+
+            /* flush connection */
+            xcb_flush(output->connection->xcb_connection);
+        }
 
         wl_signal_emit(&output->mode_change_signal, output);
     }
@@ -161,6 +455,71 @@ x11_output_add_mode_change_listener(void *o, struct wl_listener *listener)
     wl_signal_add(&output->mode_change_signal, listener);
 }
 
+static void
+x11_output_repaint_shm(x11_output_t* output)
+{
+    xcb_connection_t    *conn  = output->connection->xcb_connection;
+    xcb_void_cookie_t    cookie;
+    xcb_generic_error_t *err;
+
+    /* TODO: Set clipping area from damages
+     *       pixman_region32_rectangles(...);
+     *       xcb_set_clip_rectangles(...);
+     */
+    cookie = xcb_shm_put_image_checked(conn,
+                                       output->window,
+                                       output->gc,
+                                       output->w * output->scale,   /* total_width  */
+                                       output->h * output->scale,   /* total_height */
+                                       0,   /* src_x */
+                                       0,   /* src_y */
+                                       pixman_image_get_width(output->shm.image),  /* src_w */
+                                       pixman_image_get_height(output->shm.image), /* src_h */
+                                       0,   /* dst_x */
+                                       0,   /* dst_y */
+                                       output->depth,   /* depth */
+                                       XCB_IMAGE_FORMAT_Z_PIXMAP,   /* format */
+                                       0,   /* send_event */
+                                       output->shm.segment, /* xcb shm segment */
+                                       0);  /* offset */
+    err = xcb_request_check(conn, cookie);
+    if (err)
+    {
+        PEPPER_ERROR("Failed to put shm image, err: %d\n", err->error_code);
+        free(err);
+    }
+
+    /* XXX: frame_done callback called after 10ms, referenced from weston */
+    wl_event_source_timer_update(output->frame_done_timer, 10);
+}
+
+static void
+x11_output_repaint(void *o)
+{
+    x11_output_t *output = o;
+
+    output->renderer->draw(output->renderer, output->shm.image, NULL);
+
+    /* FIXME: hack, only pixman-render use shm.image */
+    if (output->shm.image)
+    {
+        x11_output_repaint_shm(output);
+    }
+    else
+    {
+        /* TODO: gl case */
+        PEPPER_ERROR("TODO : GL\n");
+    }
+}
+
+static void
+x11_output_add_frame_listener(void *o, struct wl_listener *listener)
+{
+    x11_output_t *output = o;
+    wl_signal_add(&output->frame_signal, listener);
+}
+
+/* X11 output interface to export for PePPer core */
 static const pepper_output_interface_t x11_output_interface =
 {
     x11_output_destroy,
@@ -174,6 +533,9 @@ static const pepper_output_interface_t x11_output_interface =
     x11_output_get_mode_count,
     x11_output_get_mode,
     x11_output_set_mode,
+
+    x11_output_repaint,
+    x11_output_add_frame_listener,
 };
 
 static void
@@ -184,18 +546,24 @@ handle_connection_destroy(struct wl_listener *listener, void *data)
 }
 
 PEPPER_API pepper_output_t *
-pepper_x11_output_create(pepper_x11_connection_t *connection, int32_t w, int32_t h)
+pepper_x11_output_create(pepper_x11_connection_t *connection,
+                         int32_t w,
+                         int32_t h,
+                         const char *renderer)
 {
-    static const char   *window_name = "PePPer Compositor";
-    static const char   *class_name  = "pepper-1\0PePPer Compositor";
+    static const char       *window_name = "PePPer Compositor";
+    static const char       *class_name  = "pepper-1\0PePPer Compositor";
+
+    pepper_output_t         *base;
+    x11_output_t            *output;
 
-    pepper_output_t     *base;
-    x11_output_t        *output;
+    struct wl_display       *wldisplay;
+    struct wl_event_loop    *loop;
 
     output = pepper_calloc(1, sizeof(x11_output_t));
     if (!output)
     {
-        PEPPER_ERROR("x11:output:%s: memory allocation failed", __FUNCTION__);
+        PEPPER_ERROR("memory allocation failed");
         return NULL;
     }
 
@@ -209,14 +577,15 @@ pepper_x11_output_create(pepper_x11_connection_t *connection, int32_t w, int32_t
     /* Hard-Coded: scale value to 1. */
     output->scale = 1;
 
-    /* create X11 window */
+    /* Create X11 window */
     {
         uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
         uint32_t values[2] = {
                 connection->screen->white_pixel,
-                0
+                XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY
         };
         xcb_size_hints_t hints;
+        xcb_atom_t list[1];
 
         output->window = xcb_generate_id(connection->xcb_connection);
         xcb_create_window(connection->xcb_connection,
@@ -233,7 +602,6 @@ pepper_x11_output_create(pepper_x11_connection_t *connection, int32_t w, int32_t
                           mask,
                           values);
 
-
         /* cannot resize */
         memset(&hints, 0, sizeof(hints));
         hints.flags = WM_NORMAL_HINTS_MAX_SIZE | WM_NORMAL_HINTS_MIN_SIZE;
@@ -260,6 +628,15 @@ pepper_x11_output_create(pepper_x11_connection_t *connection, int32_t w, int32_t
                             connection->atom.string, 8,
                             strlen(class_name), class_name);
 
+        /* set property to receive wm_delete_window message */
+        list[0] = connection->atom.wm_delete_window;
+       xcb_change_property(connection->xcb_connection, XCB_PROP_MODE_REPLACE,
+                           output->window,
+                           connection->atom.wm_protocols,
+                           XCB_ATOM_ATOM, 32,
+                           1, list);
+
+
         xcb_map_window(connection->xcb_connection, output->window);
 
         if (connection->use_xinput)
@@ -269,25 +646,37 @@ pepper_x11_output_create(pepper_x11_connection_t *connection, int32_t w, int32_t
         wl_list_insert(&connection->outputs, &output->link);
 
         xcb_flush(connection->xcb_connection);
+
+        x11_output_wait_for_map(output);
     }
 
+    /* Init signals and listeners */
     wl_signal_init(&output->destroy_signal);
     wl_signal_init(&output->mode_change_signal);
+    wl_signal_init(&output->frame_signal);
+
+    wldisplay = pepper_compositor_get_display(connection->compositor);
+    loop = wl_display_get_event_loop(wldisplay);
+    output->frame_done_timer = wl_event_loop_add_timer(loop, frame_done_handler, output);
 
-    x11_output_visual_iterate(output);
+    output->conn_destroy_listener.notify = handle_connection_destroy;
+    wl_signal_add(&connection->destroy_signal, &output->conn_destroy_listener);
+
+    /* Init renderer */
+    renderer_init(output, renderer);
 
+    /* Register output object */
     base = pepper_compositor_add_output(connection->compositor,
                                         &x11_output_interface,
                                         output);
     if (!base)
     {
-        PEPPER_ERROR("x11:output:%s: pepper_compositor_add_output failed\n", __FUNCTION__);
+        PEPPER_ERROR("pepper_compositor_add_output failed\n");
         x11_output_destroy(output);
         return NULL;
     }
 
-    output->conn_destroy_listener.notify = handle_connection_destroy;
-    wl_signal_add(&connection->destroy_signal, &output->conn_destroy_listener);
+    output->base = base;
 
     return base;
 }