]> git.sesse.net Git - vlc/commitdiff
Converted vout xcb to "vout display" API.
authorLaurent Aimar <fenrir@videolan.org>
Sat, 8 Aug 2009 23:20:26 +0000 (01:20 +0200)
committerLaurent Aimar <fenrir@videolan.org>
Sat, 8 Aug 2009 23:21:32 +0000 (01:21 +0200)
modules/video_output/xcb/common.c
modules/video_output/xcb/events.c
modules/video_output/xcb/x11.c
modules/video_output/xcb/xcb_vlc.h
modules/video_output/xcb/xvideo.c

index 6e4fe840d09985bd0de2057ccb2570210116d8f6..180e22b71f59c73f8002494fda808a81780b69c5 100644 (file)
 #include <xcb/shm.h>
 
 #include <vlc_common.h>
-#include <vlc_vout.h>
-#include <vlc_vout_window.h>
+#include <vlc_vout_display.h>
 
 #include "xcb_vlc.h"
 
+/**
+ * Check for an error
+ */
+int CheckError (vout_display_t *vd, xcb_connection_t *conn,
+                const char *str, xcb_void_cookie_t ck)
+{
+    xcb_generic_error_t *err;
+
+    err = xcb_request_check (conn, ck);
+    if (err)
+    {
+        msg_Err (vd, "%s: X11 error %d", str, err->error_code);
+        return VLC_EGENERIC;
+    }
+    return VLC_SUCCESS;
+}
+
 /**
  * Connect to the X server.
  */
@@ -62,7 +78,7 @@ xcb_connection_t *Connect (vlc_object_t *obj)
  * Create a VLC video X window object, find the corresponding X server screen,
  * and probe the MIT-SHM extension.
  */
-vout_window_t *GetWindow (vout_thread_t *obj,
+vout_window_t *GetWindow (vout_display_t *vd,
                           xcb_connection_t *conn,
                           const xcb_screen_t **restrict pscreen,
                           bool *restrict pshm)
@@ -73,14 +89,13 @@ vout_window_t *GetWindow (vout_thread_t *obj,
 
     memset( &wnd_cfg, 0, sizeof(wnd_cfg) );
     wnd_cfg.type = VOUT_WINDOW_TYPE_XID;
-    wnd_cfg.width  = obj->i_window_width;
-    wnd_cfg.height = obj->i_window_height;
-
-    vout_window_t *wnd = vout_window_New (VLC_OBJECT(obj), NULL, &wnd_cfg);
+    wnd_cfg.width  = vd->cfg->display.width;
+    wnd_cfg.height = vd->cfg->display.height;
 
+    vout_window_t *wnd = vout_display_NewWindow (vd, &wnd_cfg);
     if (wnd == NULL)
     {
-        msg_Err (obj, "parent window not available");
+        msg_Err (vd, "parent window not available");
         return NULL;
     }
     else
@@ -92,7 +107,7 @@ vout_window_t *GetWindow (vout_thread_t *obj,
         geo = xcb_get_geometry_reply (conn, ck, NULL);
         if (geo == NULL)
         {
-            msg_Err (obj, "parent window not valid");
+            msg_Err (vd, "parent window not valid");
             goto error;
         }
         root = geo->root;
@@ -116,13 +131,13 @@ vout_window_t *GetWindow (vout_thread_t *obj,
 
     if (screen == NULL)
     {
-        msg_Err (obj, "parent window screen not found");
+        msg_Err (vd, "parent window screen not found");
         goto error;
     }
-    msg_Dbg (obj, "using screen 0x%"PRIx32, root);
+    msg_Dbg (vd, "using screen 0x%"PRIx32, root);
 
     /* Check MIT-SHM shared memory support */
-    bool shm = var_CreateGetBool (obj, "x11-shm") > 0;
+    bool shm = var_CreateGetBool (vd, "x11-shm") > 0;
     if (shm)
     {
         xcb_shm_query_version_cookie_t ck;
@@ -132,8 +147,8 @@ vout_window_t *GetWindow (vout_thread_t *obj,
         r = xcb_shm_query_version_reply (conn, ck, NULL);
         if (!r)
         {
-            msg_Err (obj, "shared memory (MIT-SHM) not available");
-            msg_Warn (obj, "display will be slow");
+            msg_Err (vd, "shared memory (MIT-SHM) not available");
+            msg_Warn (vd, "display will be slow");
             shm = false;
         }
         free (r);
@@ -144,7 +159,7 @@ vout_window_t *GetWindow (vout_thread_t *obj,
     return wnd;
 
 error:
-    vout_window_Delete (wnd);
+    vout_display_DeleteWindow (vd, wnd);
     return NULL;
 }
 
@@ -168,19 +183,22 @@ int GetWindowSize (struct vout_window_t *wnd, xcb_connection_t *conn,
 
 /**
  * Initialize a picture buffer as shared memory, according to the video output
- * format. If a XCB connection pointer is supplied, the segment is attached to
+ * format. If a attach is true, the segment is attached to
  * the X server (MIT-SHM extension).
  */
-int PictureAlloc (vout_thread_t *vout, picture_t *pic, size_t size,
-                  xcb_connection_t *conn)
+int PictureResourceAlloc (vout_display_t *vd, picture_resource_t *res, size_t size,
+                          xcb_connection_t *conn, bool attach)
 {
-    assert (pic->i_status == FREE_PICTURE);
+    res->p_sys = malloc (sizeof(*res->p_sys));
+    if (!res->p_sys)
+        return VLC_EGENERIC;
 
     /* Allocate shared memory segment */
     int id = shmget (IPC_PRIVATE, size, IPC_CREAT | 0700);
     if (id == -1)
     {
-        msg_Err (vout, "shared memory allocation error: %m");
+        msg_Err (vd, "shared memory allocation error: %m");
+        free (res->p_sys);
         return VLC_EGENERIC;
     }
 
@@ -188,13 +206,14 @@ int PictureAlloc (vout_thread_t *vout, picture_t *pic, size_t size,
     void *shm = shmat (id, NULL, 0 /* read/write */);
     if (-1 == (intptr_t)shm)
     {
-        msg_Err (vout, "shared memory attachment error: %m");
+        msg_Err (vd, "shared memory attachment error: %m");
         shmctl (id, IPC_RMID, 0);
+        free (res->p_sys);
         return VLC_EGENERIC;
     }
 
     xcb_shm_seg_t segment;
-    if (conn != NULL)
+    if (attach)
     {
         /* Attach the segment to X */
         xcb_void_cookie_t ck;
@@ -202,9 +221,9 @@ int PictureAlloc (vout_thread_t *vout, picture_t *pic, size_t size,
         segment = xcb_generate_id (conn);
         ck = xcb_shm_attach_checked (conn, segment, id, 1);
 
-        if (CheckError (vout, "shared memory server-side error", ck))
+        if (CheckError (vd, conn, "shared memory server-side error", ck))
         {
-            msg_Info (vout, "using buggy X11 server - SSH proxying?");
+            msg_Info (vd, "using buggy X11 server - SSH proxying?");
             segment = 0;
         }
     }
@@ -212,67 +231,23 @@ int PictureAlloc (vout_thread_t *vout, picture_t *pic, size_t size,
         segment = 0;
 
     shmctl (id, IPC_RMID, 0);
-    pic->p_sys = (void *)(uintptr_t)segment;
-    pic->p->p_pixels = shm;
-    pic->i_status = DESTROYED_PICTURE;
-    pic->i_type = DIRECT_PICTURE;
+    res->p_sys->segment = segment;
+    res->p->p_pixels = shm;
     return VLC_SUCCESS;
 }
 
 /**
  * Release picture private data: detach the shared memory segment.
  */
-void PictureFree (picture_t *pic, xcb_connection_t *conn)
+void PictureResourceFree (picture_resource_t *res, xcb_connection_t *conn)
 {
-    xcb_shm_seg_t segment = (uintptr_t)pic->p_sys;
+    xcb_shm_seg_t segment = res->p_sys->segment;
 
     if (segment != 0)
     {
         assert (conn != NULL);
         xcb_shm_detach (conn, segment);
     }
-    shmdt (pic->p->p_pixels);
+    shmdt (res->p->p_pixels);
 }
 
-/**
- * Video output thread management stuff.
- * FIXME: Much of this should move to core
- */
-void CommonManage (vout_thread_t *vout)
-{
-    if (vout->i_changes & VOUT_SCALE_CHANGE)
-    {
-        vout->b_autoscale = var_GetBool (vout, "autoscale");
-        vout->i_zoom = ZOOM_FP_FACTOR;
-        vout->i_changes &= ~VOUT_SCALE_CHANGE;
-        vout->i_changes |= VOUT_SIZE_CHANGE;
-    }
-
-    if (vout->i_changes & VOUT_ZOOM_CHANGE)
-    {
-        vout->b_autoscale = false;
-        vout->i_zoom = var_GetFloat (vout, "scale") * ZOOM_FP_FACTOR;
-        vout->i_changes &= ~VOUT_ZOOM_CHANGE;
-        vout->i_changes |= VOUT_SIZE_CHANGE;
-    }
-
-    if (vout->i_changes & VOUT_CROP_CHANGE)
-    {
-        vout->fmt_out.i_x_offset = vout->fmt_in.i_x_offset;
-        vout->fmt_out.i_y_offset = vout->fmt_in.i_y_offset;
-        vout->fmt_out.i_visible_width = vout->fmt_in.i_visible_width;
-        vout->fmt_out.i_visible_height = vout->fmt_in.i_visible_height;
-        vout->i_changes &= ~VOUT_CROP_CHANGE;
-        vout->i_changes |= VOUT_SIZE_CHANGE;
-    }
-
-    if (vout->i_changes & VOUT_ASPECT_CHANGE)
-    {
-        vout->fmt_out.i_aspect = vout->fmt_in.i_aspect;
-        vout->fmt_out.i_sar_num = vout->fmt_in.i_sar_num;
-        vout->fmt_out.i_sar_den = vout->fmt_in.i_sar_den;
-        vout->output.i_aspect = vout->fmt_in.i_aspect;
-        vout->i_changes &= ~VOUT_ASPECT_CHANGE;
-        vout->i_changes |= VOUT_SIZE_CHANGE;
-    }
-}
index b279da40474c44372044c1863040bb4986fb7e3d..e3c5aa32d0833b4a1fbe3f3a1841da532ade83b1 100644 (file)
@@ -30,7 +30,7 @@
 #include <xcb/xcb.h>
 
 #include <vlc_common.h>
-#include <vlc_vout.h>
+#include <vlc_vout_display.h>
 
 #include "xcb_vlc.h"
 
   * Otherwise, we'd var_OrInteger() and var_NandInteger() functions...
  */
 
-static void HandleButtonPress (vout_thread_t *vout,
+/* FIXME we assume direct mapping between XCB and VLC */
+static void HandleButtonPress (vout_display_t *vd,
                                xcb_button_press_event_t *ev)
 {
-    unsigned buttons = var_GetInteger (vout, "mouse-button-down");
-    buttons |= (1 << (ev->detail - 1));
-    var_SetInteger (vout, "mouse-button-down", buttons);
+    vout_display_SendEventMousePressed (vd, ev->detail - 1);
 }
 
-static void HandleButtonRelease (vout_thread_t *vout,
+static void HandleButtonRelease (vout_display_t *vd,
                                  xcb_button_release_event_t *ev)
 {
-    unsigned buttons = var_GetInteger (vout, "mouse-button-down");
-    buttons &= ~(1 << (ev->detail - 1));
-    var_SetInteger (vout, "mouse-button-down", buttons);
-
-    switch (ev->detail)
-    {
-        case 1: /* left mouse button */
-            var_SetBool (vout, "mouse-clicked", true);
-            var_SetBool (vout->p_libvlc, "intf-popupmenu", false);
-            break;
-        case 3:
-            var_SetBool (vout->p_libvlc, "intf-popupmenu", true);
-            break;
-    }
+    vout_display_SendEventMouseReleased (vd, ev->detail - 1);
 }
 
-static void HandleMotionNotify (vout_thread_t *vout,
+static void HandleMotionNotify (vout_display_t *vd,
                                 xcb_motion_notify_event_t *ev)
 {
-    unsigned x, y, width, height;
-    int v;
-
-    vout_PlacePicture (vout, vout->output.i_width, vout->output.i_height,
-                       &x, &y, &width, &height);
-    v = vout->fmt_in.i_x_offset
-        + ((ev->event_x - x) * vout->fmt_in.i_visible_width / width);
-    if (v < 0)
-        v = 0; /* to the left of the picture */
-    else if ((unsigned)v > vout->fmt_in.i_width)
-        v = vout->fmt_in.i_width; /* to the right of the picture */
-    var_SetInteger (vout, "mouse-x", v);
-
-    v = vout->fmt_in.i_y_offset
-        + ((ev->event_y - y) * vout->fmt_in.i_visible_height / height);
-    if (v < 0)
-        v = 0; /* above the picture */
-    else if ((unsigned)v > vout->fmt_in.i_height)
-        v = vout->fmt_in.i_height; /* below the picture */
-    var_SetInteger (vout, "mouse-y", v);
+    vout_display_place_t place;
+
+    /* TODO it could be saved */
+    vout_display_PlacePicture (&place, &vd->source, vd->cfg, false);
+
+    if (place.width <= 0 || place.height <= 0)
+        return;
+
+    const int x = vd->source.i_x_offset +
+        (int64_t)(ev->event_x -0*place.x) * vd->source.i_visible_width / place.width;
+    const int y = vd->source.i_y_offset +
+        (int64_t)(ev->event_y -0*place.y) * vd->source.i_visible_height/ place.height;
+
+    /* TODO show the cursor ? */
+    if (x >= vd->source.i_x_offset && x < vd->source.i_x_offset + vd->source.i_visible_width &&
+        y >= vd->source.i_y_offset && y < vd->source.i_y_offset + vd->source.i_visible_height)
+        vout_display_SendEventMouseMoved (vd, x, y);
+}
+
+static void
+HandleParentStructure (vout_display_t *vd, xcb_configure_notify_event_t *ev)
+{
+    if (ev->width  != vd->cfg->display.width ||
+        ev->height != vd->cfg->display.height)
+        vout_display_SendEventDisplaySize (vd, ev->width, ev->height);
 }
 
 /**
  * Process an X11 event.
  */
-int ProcessEvent (vout_thread_t *vout, xcb_connection_t *conn,
-                  xcb_window_t window, xcb_generic_event_t *ev)
+static int ProcessEvent (vout_display_t *vd,
+                         xcb_window_t window, xcb_generic_event_t *ev)
 {
     switch (ev->response_type & 0x7f)
     {
         case XCB_BUTTON_PRESS:
-            HandleButtonPress (vout, (xcb_button_press_event_t *)ev);
+            HandleButtonPress (vd, (xcb_button_press_event_t *)ev);
             break;
 
         case XCB_BUTTON_RELEASE:
-            HandleButtonRelease (vout, (xcb_button_release_event_t *)ev);
+            HandleButtonRelease (vd, (xcb_button_release_event_t *)ev);
             break;
 
         case XCB_MOTION_NOTIFY:
-            HandleMotionNotify (vout, (xcb_motion_notify_event_t *)ev);
+            HandleMotionNotify (vd, (xcb_motion_notify_event_t *)ev);
             break;
 
         case XCB_CONFIGURE_NOTIFY:
@@ -117,14 +108,41 @@ int ProcessEvent (vout_thread_t *vout, xcb_connection_t *conn,
                 (xcb_configure_notify_event_t *)ev;
 
             assert (cn->window != window);
-            HandleParentStructure (vout, conn, window, cn);
+            HandleParentStructure (vd, cn);
             break;
         }
 
+        /* FIXME I am not sure it is the right one */
+        case XCB_DESTROY_NOTIFY:
+            vout_display_SendEventClose (vd);
+            break;
+
         default:
-            msg_Dbg (vout, "unhandled event %"PRIu8, ev->response_type);
+            msg_Dbg (vd, "unhandled event %"PRIu8, ev->response_type);
     }
 
     free (ev);
     return VLC_SUCCESS;
 }
+
+/**
+ * Process incoming X events.
+ */
+int ManageEvent (vout_display_t *vd, xcb_connection_t *conn, xcb_window_t window)
+{
+    xcb_generic_event_t *ev;
+
+    while ((ev = xcb_poll_for_event (conn)) != NULL)
+        ProcessEvent (vd, window, ev);
+
+    if (xcb_connection_has_error (conn))
+    {
+        msg_Err (vd, "X server failure");
+        return VLC_EGENERIC;
+    }
+
+    return VLC_SUCCESS;
+}
+
+
+
index 9c0ea974bddba1a7fcd05dc7f37a3df3c5d62078..eb72a932fab574bccf8a1c2229bbe5848ddb2abf 100644 (file)
@@ -32,8 +32,8 @@
 
 #include <vlc_common.h>
 #include <vlc_plugin.h>
-#include <vlc_vout.h>
-#include <vlc_vout_window.h>
+#include <vlc_vout_display.h>
+#include <vlc_picture_pool.h>
 
 #include "xcb_vlc.h"
 
@@ -57,7 +57,7 @@ vlc_module_begin ()
     set_description (N_("(Experimental) XCB video output"))
     set_category (CAT_VIDEO)
     set_subcategory (SUBCAT_VIDEO_VOUT)
-    set_capability ("video output", 0)
+    set_capability ("vout display", 0)
     set_callbacks (Open, Close)
 
     add_string ("x11-display", NULL, NULL,
@@ -65,7 +65,13 @@ vlc_module_begin ()
     add_bool ("x11-shm", true, NULL, SHM_TEXT, SHM_LONGTEXT, true)
 vlc_module_end ()
 
-struct vout_sys_t
+/* It must be large enough to absorb the server display jitter but it is
+ * useless to used a too large value, direct rendering cannot be used with
+ * xcb x11
+ */
+#define MAX_PICTURES (3)
+
+struct vout_display_sys_t
 {
     xcb_connection_t *conn;
     vout_window_t *embed; /* VLC window (when windowed) */
@@ -77,40 +83,29 @@ struct vout_sys_t
     uint8_t pad; /* scanline pad */
     uint8_t depth; /* useful bits per pixel */
     uint8_t byte_order; /* server byte order */
-};
 
-static int Init (vout_thread_t *);
-static void Deinit (vout_thread_t *);
-static void Display (vout_thread_t *, picture_t *);
-static int Manage (vout_thread_t *);
-static int Control (vout_thread_t *, int, va_list);
-
-int CheckError (vout_thread_t *vout, const char *str, xcb_void_cookie_t ck)
-{
-    xcb_generic_error_t *err;
+    picture_pool_t *pool; /* picture pool */
+    picture_resource_t resource[MAX_PICTURES];
+};
 
-    err = xcb_request_check (vout->p_sys->conn, ck);
-    if (err)
-    {
-        msg_Err (vout, "%s: X11 error %d", str, err->error_code);
-        return VLC_EGENERIC;
-    }
-    return VLC_SUCCESS;
-}
+static picture_t *Get (vout_display_t *);
+static void Display (vout_display_t *, picture_t *);
+static int Control (vout_display_t *, int, va_list);
+static void Manage (vout_display_t *);
 
-#define p_vout vout
+static void ResetPictures (vout_display_t *);
 
 /**
  * Probe the X server.
  */
 static int Open (vlc_object_t *obj)
 {
-    vout_thread_t *vout = (vout_thread_t *)obj;
-    vout_sys_t *p_sys = malloc (sizeof (*p_sys));
+    vout_display_t *vd = (vout_display_t *)obj;
+    vout_display_sys_t *p_sys = malloc (sizeof (*p_sys));
     if (p_sys == NULL)
         return VLC_ENOMEM;
 
-    vout->p_sys = p_sys;
+    vd->sys = p_sys;
 
     /* Connect to X */
     p_sys->conn = Connect (obj);
@@ -122,7 +117,7 @@ static int Open (vlc_object_t *obj)
 
     /* Get window */
     const xcb_screen_t *scr;
-    p_sys->embed = GetWindow (vout, p_sys->conn, &scr, &p_sys->shm);
+    p_sys->embed = GetWindow (vd, p_sys->conn, &scr, &p_sys->shm);
     if (p_sys->embed == NULL)
     {
         xcb_disconnect (p_sys->conn);
@@ -133,6 +128,9 @@ static int Open (vlc_object_t *obj)
     const xcb_setup_t *setup = xcb_get_setup (p_sys->conn);
     p_sys->byte_order = setup->image_byte_order;
 
+    /* */
+    video_format_t fmt_pic = vd->fmt;
+
     /* Determine our video format. Normally, this is done in pf_init(), but
      * this plugin always uses the same format for a given X11 screen. */
     xcb_visualid_t vid = 0;
@@ -213,12 +211,12 @@ static int Open (vlc_object_t *obj)
         if (!vid)
             continue; /* The screen does not *really* support this depth */
 
-        vout->fmt_out.i_chroma = vout->output.i_chroma = chroma;
+        fmt_pic.i_chroma = chroma;
         if (!gray)
         {
-            vout->fmt_out.i_rmask = vout->output.i_rmask = vt->red_mask;
-            vout->fmt_out.i_gmask = vout->output.i_gmask = vt->green_mask;
-            vout->fmt_out.i_bmask = vout->output.i_bmask = vt->blue_mask;
+            fmt_pic.i_rmask = vt->red_mask;
+            fmt_pic.i_gmask = vt->green_mask;
+            fmt_pic.i_bmask = vt->blue_mask;
         }
         p_sys->bpp = fmt->bits_per_pixel;
         p_sys->pad = fmt->scanline_pad;
@@ -227,12 +225,12 @@ static int Open (vlc_object_t *obj)
 
     if (depth == 0)
     {
-        msg_Err (vout, "no supported pixmap formats or visual types");
+        msg_Err (vd, "no supported pixmap formats or visual types");
         goto error;
     }
 
-    msg_Dbg (vout, "using X11 visual ID 0x%"PRIx32, vid);
-    msg_Dbg (vout, " %"PRIu8" bits per pixels, %"PRIu8" bits line pad",
+    msg_Dbg (vd, "using X11 visual ID 0x%"PRIx32, vid);
+    msg_Dbg (vd, " %"PRIu8" bits per pixels, %"PRIu8" bits line pad",
              p_sys->bpp, p_sys->pad);
 
     /* Create colormap (needed to select non-default visual) */
@@ -263,23 +261,41 @@ static int Open (vlc_object_t *obj)
                                        p_sys->embed->handle.xid, 0, 0, 1, 1, 0,
                                        XCB_WINDOW_CLASS_INPUT_OUTPUT,
                                        vid, mask, values);
-        if (CheckError (vout, "cannot create X11 window", c))
+        if (CheckError (vd, p_sys->conn, "cannot create X11 window", c))
             goto error;
         p_sys->window = window;
-        msg_Dbg (vout, "using X11 window %08"PRIx32, p_sys->window);
+        msg_Dbg (vd, "using X11 window %08"PRIx32, p_sys->window);
         xcb_map_window (p_sys->conn, window);
     }
 
     /* Create graphic context (I wonder why the heck do we need this) */
     p_sys->gc = xcb_generate_id (p_sys->conn);
     xcb_create_gc (p_sys->conn, p_sys->gc, p_sys->window, 0, NULL);
-    msg_Dbg (vout, "using X11 graphic context %08"PRIx32, p_sys->gc);
+    msg_Dbg (vd, "using X11 graphic context %08"PRIx32, p_sys->gc);
+
+    /* */
+    p_sys->pool = NULL;
+
+    /* */
+    vout_display_info_t info = vd->info;
+    info.has_pictures_invalid = true;
+
+    /* Setup vout_display_t once everything is fine */
+    vd->fmt = fmt_pic;
+    vd->info = info;
+
+    vd->get = Get;
+    vd->prepare = NULL;
+    vd->display = Display;
+    vd->control = Control;
+    vd->manage = Manage;
+
+    /* */
+    unsigned width, height;
+    if (!GetWindowSize (p_sys->embed, p_sys->conn, &width, &height))
+        vout_display_SendEventDisplaySize (vd, width, height);
+    vout_display_SendEventFullscreen (vd, false);
 
-    vout->pf_init = Init;
-    vout->pf_end = Deinit;
-    vout->pf_display = Display;
-    vout->pf_manage = Manage;
-    vout->pf_control = Control;
     return VLC_SUCCESS;
 
 error:
@@ -293,174 +309,219 @@ error:
  */
 static void Close (vlc_object_t *obj)
 {
-    vout_thread_t *vout = (vout_thread_t *)obj;
-    vout_sys_t *p_sys = vout->p_sys;
+    vout_display_t *vd = (vout_display_t *)obj;
+    vout_display_sys_t *p_sys = vd->sys;
 
-    vout_window_Delete (p_sys->embed);
+    ResetPictures (vd);
+    vout_display_DeleteWindow (vd, p_sys->embed);
     /* colormap and window are garbage-collected by X */
     xcb_disconnect (p_sys->conn);
     free (p_sys);
 }
 
-
 /**
- * Allocate drawable window and picture buffers.
+ * Return a direct buffer
  */
-static int Init (vout_thread_t *vout)
+static picture_t *Get (vout_display_t *vd)
 {
-    vout_sys_t *p_sys = vout->p_sys;
-    unsigned x, y, width, height;
+    vout_display_sys_t *p_sys = vd->sys;
 
-    if (GetWindowSize (p_sys->embed, p_sys->conn, &width, &height))
-        return VLC_EGENERIC;
-    vout_PlacePicture (vout, width, height, &x, &y, &width, &height);
-
-    const uint32_t values[] = { x, y, width, height, };
-    xcb_configure_window (p_sys->conn, p_sys->window,
-                          XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y |
-                          XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
-                          values);
-
-    /* FIXME: I don't get the subtlety between output and fmt_out here */
-    vout->fmt_out.i_visible_width = width;
-    vout->fmt_out.i_visible_height = height;
-    vout->fmt_out.i_sar_num = vout->fmt_out.i_sar_den = 1;
-
-    vout->output.i_width = vout->fmt_out.i_width =
-        width * vout->fmt_in.i_width / vout->fmt_in.i_visible_width;
-    vout->output.i_height = vout->fmt_out.i_height =
-        height * vout->fmt_in.i_height / vout->fmt_in.i_visible_height;
-    vout->fmt_out.i_x_offset =
-        width * vout->fmt_in.i_x_offset / vout->fmt_in.i_visible_width;
-    p_vout->fmt_out.i_y_offset =
-        height * vout->fmt_in.i_y_offset / vout->fmt_in.i_visible_height;
-
-    assert (height > 0);
-    vout->output.i_aspect = vout->fmt_out.i_aspect =
-        width * VOUT_ASPECT_FACTOR / height;
-
-    /* Allocate picture buffers */
-    I_OUTPUTPICTURES = 0;
-    for (size_t index = 0; I_OUTPUTPICTURES < 2; index++)
+    if (!p_sys->pool)
     {
-        picture_t *pic = vout->p_picture + index;
+        vout_display_place_t place;
 
-        if (index > sizeof (vout->p_picture) / sizeof (pic))
-            break;
-        if (pic->i_status != FREE_PICTURE)
-            continue;
+        vout_display_PlacePicture (&place, &vd->source, vd->cfg, false);
 
-        picture_Setup (pic, vout->output.i_chroma,
-                       vout->output.i_width, vout->output.i_height,
-                       vout->output.i_aspect);
-        if (PictureAlloc (vout, pic, pic->p->i_pitch * pic->p->i_lines,
-                          p_sys->shm ? p_sys->conn : NULL))
-            break;
-        PP_OUTPUTPICTURE[I_OUTPUTPICTURES++] = pic;
+        /* */
+        const uint32_t values[] = { place.x, place.y, place.width, place.height };
+        xcb_configure_window (p_sys->conn, p_sys->window,
+                              XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y |
+                              XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
+                              values);
+
+        picture_t *pic = picture_NewFromFormat (&vd->fmt);
+        if (!pic)
+            return NULL;
+
+        assert (pic->i_planes == 1);
+        memset (p_sys->resource, 0, sizeof(p_sys->resource));
+
+        unsigned count;
+        picture_t *pic_array[MAX_PICTURES];
+        for (count = 0; count < MAX_PICTURES; count++)
+        {
+            picture_resource_t *res = &p_sys->resource[count];
+
+            res->p->i_lines = pic->p->i_lines;
+            res->p->i_pitch = pic->p->i_pitch;
+            if (PictureResourceAlloc (vd, res, res->p->i_pitch * res->p->i_lines,
+                                      p_sys->conn, p_sys->shm))
+                break;
+            pic_array[count] = picture_NewFromResource (&vd->fmt, res);
+            if (!pic_array[count])
+            {
+                PictureResourceFree (res, p_sys->conn);
+                memset (res, 0, sizeof(*res));
+                break;
+            }
+        }
+        picture_Release (pic);
+
+        if (count == 0)
+            return NULL;
+
+        p_sys->pool = picture_pool_New (count, pic_array);
+        if (!p_sys->pool)
+        {
+            /* TODO release picture resources */
+            return NULL;
+        }
+        /* FIXME should also do it in case of error ? */
+        xcb_flush (p_sys->conn);
     }
-    xcb_flush (p_sys->conn);
-    return VLC_SUCCESS;
-}
 
-/**
- * Free picture buffers.
- */
-static void Deinit (vout_thread_t *vout)
-{
-    for (int i = 0; i < I_OUTPUTPICTURES; i++)
-        PictureFree (PP_OUTPUTPICTURE[i], vout->p_sys->conn);
+    return picture_pool_Get (p_sys->pool);
 }
 
 /**
  * Sends an image to the X server.
  */
-static void Display (vout_thread_t *vout, picture_t *pic)
+static void Display (vout_display_t *vd, picture_t *pic)
 {
-    vout_sys_t *p_sys = vout->p_sys;
-    xcb_shm_seg_t segment = (uintptr_t)pic->p_sys;
+    vout_display_sys_t *p_sys = vd->sys;
+    xcb_shm_seg_t segment = pic->p_sys->segment;
 
     if (segment != 0)
         xcb_shm_put_image (p_sys->conn, p_sys->window, p_sys->gc,
           /* real width */ pic->p->i_pitch / pic->p->i_pixel_pitch,
          /* real height */ pic->p->i_lines,
-                   /* x */ vout->fmt_out.i_x_offset,
-                   /* y */ vout->fmt_out.i_y_offset,
-               /* width */ vout->fmt_out.i_visible_width,
-              /* height */ vout->fmt_out.i_visible_height,
+                   /* x */ vd->fmt.i_x_offset,
+                   /* y */ vd->fmt.i_y_offset,
+               /* width */ vd->fmt.i_visible_width,
+              /* height */ vd->fmt.i_visible_height,
                            0, 0, p_sys->depth, XCB_IMAGE_FORMAT_Z_PIXMAP,
                            0, segment, 0);
     else
     {
-        const size_t offset = vout->fmt_out.i_y_offset * pic->p->i_pitch;
-        const unsigned lines = pic->p->i_lines - vout->fmt_out.i_y_offset;
+        const size_t offset = vd->fmt.i_y_offset * pic->p->i_pitch;
+        const unsigned lines = pic->p->i_lines - vd->fmt.i_y_offset;
 
         xcb_put_image (p_sys->conn, XCB_IMAGE_FORMAT_Z_PIXMAP,
                        p_sys->window, p_sys->gc,
                        pic->p->i_pitch / pic->p->i_pixel_pitch,
-                       lines, -vout->fmt_out.i_x_offset, 0, 0, p_sys->depth,
+                       lines, -vd->fmt.i_x_offset, 0, 0, p_sys->depth,
                        pic->p->i_pitch * lines, pic->p->p_pixels + offset);
     }
     xcb_flush (p_sys->conn);
+
+    /* FIXME might be WAY better to wait in some case (be carefull with
+     * VOUT_DISPLAY_RESET_PICTURES if done) + does not work with
+     * vout_display wrapper. */
+    picture_Release (pic);
 }
 
-/**
- * Process incoming X events.
- */
-static int Manage (vout_thread_t *vout)
+static int Control (vout_display_t *vd, int query, va_list ap)
 {
-    vout_sys_t *p_sys = vout->p_sys;
-    xcb_generic_event_t *ev;
-
-    while ((ev = xcb_poll_for_event (p_sys->conn)) != NULL)
-        ProcessEvent (vout, p_sys->conn, p_sys->window, ev);
+    vout_display_sys_t *p_sys = vd->sys;
 
-    if (xcb_connection_has_error (p_sys->conn))
+    switch (query)
     {
-        msg_Err (vout, "X server failure");
-        return VLC_EGENERIC;
-    }
+    case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
+    {
+        const vout_display_cfg_t *p_cfg =
+            (const vout_display_cfg_t*)va_arg (ap, const vout_display_cfg_t *);
 
-    CommonManage (vout); /* FIXME: <-- move that to core */
-    return VLC_SUCCESS;
-}
+        if (vout_window_SetSize (p_sys->embed,
+                                  p_cfg->display.width,
+                                  p_cfg->display.height))
+            return VLC_EGENERIC;
 
-void
-HandleParentStructure (vout_thread_t *vout, xcb_connection_t *conn,
-                       xcb_window_t xid, xcb_configure_notify_event_t *ev)
-{
-    unsigned width, height, x, y;
+        vout_display_place_t place;
+        vout_display_PlacePicture (&place, &vd->source, p_cfg, false);
 
-    vout_PlacePicture (vout, ev->width, ev->height, &x, &y, &width, &height);
-    if (width != vout->fmt_out.i_visible_width
-     || height != vout->fmt_out.i_visible_height)
+        if (place.width  != vd->fmt.i_visible_width ||
+            place.height != vd->fmt.i_visible_height)
+        {
+            vout_display_SendEventPicturesInvalid (vd);
+            return VLC_SUCCESS;
+        }
+
+        /* Move the picture within the window */
+        const uint32_t values[] = { place.x, place.y };
+        xcb_configure_window (p_sys->conn, p_sys->window,
+                              XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
+                              values);
+        return VLC_SUCCESS;
+    }
+    case VOUT_DISPLAY_CHANGE_ON_TOP:
     {
-        vout->i_changes |= VOUT_SIZE_CHANGE;
-        return; /* vout will be reinitialized */
+        int b_on_top = (int)va_arg (ap, int);
+        return vout_window_SetOnTop (p_sys->embed, b_on_top);
     }
 
-    /* Move the picture within the window */
-    const uint32_t values[] = { x, y, };
-    xcb_configure_window (conn, xid,
-                          XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
-                          values);
-}
+    case VOUT_DISPLAY_CHANGE_ZOOM:
+    case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
+    case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
+    case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
+        /* I am not sure it is always necessary, but it is way simpler ... */
+        vout_display_SendEventPicturesInvalid (vd);
+        return VLC_SUCCESS;
 
-static int Control (vout_thread_t *vout, int query, va_list ap)
-{
-    switch (query)
+    case VOUT_DISPLAY_RESET_PICTURES:
     {
-    case VOUT_SET_SIZE:
-    {
-        const unsigned width  = va_arg (ap, unsigned);
-        const unsigned height = va_arg (ap, unsigned);
-        return vout_window_SetSize (vout->p_sys->embed, width, height);
-    }
-    case VOUT_SET_STAY_ON_TOP:
-    {
-        const bool is_on_top = va_arg (ap, int);
-        return vout_window_SetOnTop (vout->p_sys->embed, is_on_top);
+        ResetPictures (vd);
+
+        vout_display_place_t place;
+        vout_display_PlacePicture (&place, &vd->source, vd->cfg, false);
+
+        vd->fmt.i_width  = vd->source.i_width  * place.width  / vd->source.i_visible_width;
+        vd->fmt.i_height = vd->source.i_height * place.height / vd->source.i_visible_height;
+
+        vd->fmt.i_visible_width  = place.width;
+        vd->fmt.i_visible_height = place.height;
+        vd->fmt.i_x_offset = vd->source.i_x_offset * place.width  / vd->source.i_visible_width;
+        vd->fmt.i_y_offset = vd->source.i_y_offset * place.height / vd->source.i_visible_height;
+        return VLC_SUCCESS;
     }
+
+    /* TODO */
+#if 0
+    /* Hide the mouse. It will be send when
+     * vout_display_t::info.b_hide_mouse is false */
+    VOUT_DISPLAY_HIDE_MOUSE,
+
+    /* Ask the module to acknowledge/refuse the fullscreen state change after
+     * being requested (externaly or by VOUT_DISPLAY_EVENT_FULLSCREEN */
+    VOUT_DISPLAY_CHANGE_FULLSCREEN,     /* const vout_display_cfg_t *p_cfg */
+#endif
     default:
+        msg_Err (vd, "Unknown request in XCB vout display");
         return VLC_EGENERIC;
     }
 }
+
+static void Manage (vout_display_t *vd)
+{
+    vout_display_sys_t *p_sys = vd->sys;
+
+    ManageEvent (vd, p_sys->conn, p_sys->window);
+}
+
+static void ResetPictures (vout_display_t *vd)
+{
+    vout_display_sys_t *p_sys = vd->sys;
+
+    if (!p_sys->pool)
+        return;
+
+    for (unsigned i = 0; i < MAX_PICTURES; i++)
+    {
+        picture_resource_t *res = &p_sys->resource[i];
+
+        if (!res->p->p_pixels)
+            break;
+        PictureResourceFree (res, p_sys->conn);
+    }
+    picture_pool_Delete (p_sys->pool);
+    p_sys->pool = NULL;
+}
index aad0358e98fdab501f3370d81ab65155410279b2..88e7374772fb5002151c031c77ce22a5f78c417c 100644 (file)
 # define ORDER XCB_IMAGE_ORDER_LSB_FIRST
 #endif
 
-int CheckError (vout_thread_t *, const char *str, xcb_void_cookie_t);
-int ProcessEvent (vout_thread_t *, xcb_connection_t *, xcb_window_t,
-                  xcb_generic_event_t *);
-void HandleParentStructure (vout_thread_t *vout, xcb_connection_t *conn,
-                          xcb_window_t xid, xcb_configure_notify_event_t *ev);
+#include <vlc_picture.h>
+#include <vlc_vout_display.h>
 
+int ManageEvent (vout_display_t *vd, xcb_connection_t *conn, xcb_window_t window);
 
 /* keys.c */
 typedef struct key_handler_t key_handler_t;
@@ -40,15 +38,25 @@ void DestroyKeyHandler (key_handler_t *);
 int ProcessKeyEvent (key_handler_t *, xcb_generic_event_t *);
 
 /* common.c */
-struct vout_window_t;
-
 xcb_connection_t *Connect (vlc_object_t *obj);
-struct vout_window_t *GetWindow (vout_thread_t *obj,
+struct vout_window_t *GetWindow (vout_display_t *obj,
                                  xcb_connection_t *pconn,
                                  const xcb_screen_t **restrict pscreen,
                                  bool *restrict pshm);
 int GetWindowSize (struct vout_window_t *wnd, xcb_connection_t *conn,
                    unsigned *restrict width, unsigned *restrict height);
-int PictureAlloc (vout_thread_t *, picture_t *, size_t, xcb_connection_t *);
-void PictureFree (picture_t *pic, xcb_connection_t *conn);
-void CommonManage (vout_thread_t *);
+
+int CheckError (vout_display_t *, xcb_connection_t *conn,
+                const char *str, xcb_void_cookie_t);
+
+/* FIXME
+ * maybe it would be better to split this header in 2 */
+#include <xcb/shm.h>
+struct picture_sys_t
+{
+    xcb_shm_seg_t segment;
+};
+int PictureResourceAlloc (vout_display_t *vd, picture_resource_t *res, size_t size,
+                          xcb_connection_t *conn, bool attach);
+void PictureResourceFree (picture_resource_t *res, xcb_connection_t *conn);
+
index 0afd1c66e22a9abded65daa763451d64bed4c0fc..75ce2a5a4fe75332cd8a22811c8bc51080146575 100644 (file)
@@ -33,8 +33,8 @@
 
 #include <vlc_common.h>
 #include <vlc_plugin.h>
-#include <vlc_vout.h>
-#include <vlc_vout_window.h>
+#include <vlc_vout_display.h>
+#include <vlc_picture_pool.h>
 
 #include "xcb_vlc.h"
 
@@ -58,7 +58,7 @@ vlc_module_begin ()
     set_description (N_("(Experimental) XVideo output"))
     set_category (CAT_VIDEO)
     set_subcategory (SUBCAT_VIDEO_VOUT)
-    set_capability ("video output", 0)
+    set_capability ("vout display", 0)
     set_callbacks (Open, Close)
 
     add_string ("x11-display", NULL, NULL,
@@ -67,7 +67,9 @@ vlc_module_begin ()
     add_shortcut ("xcb-xv")
 vlc_module_end ()
 
-struct vout_sys_t
+#define MAX_PICTURES (VOUT_MAX_PICTURES)
+
+struct vout_display_sys_t
 {
     xcb_connection_t *conn;
     xcb_xv_query_adaptors_reply_t *adaptors;
@@ -81,31 +83,21 @@ struct vout_sys_t
     uint16_t height;     /* display height */
     uint32_t data_size;  /* picture byte size (for non-SHM) */
     bool shm;            /* whether to use MIT-SHM */
-};
 
-static int Init (vout_thread_t *);
-static void Deinit (vout_thread_t *);
-static void Display (vout_thread_t *, picture_t *);
-static int Manage (vout_thread_t *);
-static int Control (vout_thread_t *, int, va_list);
-
-int CheckError (vout_thread_t *vout, const char *str, xcb_void_cookie_t ck)
-{
-    xcb_generic_error_t *err;
+    xcb_xv_query_image_attributes_reply_t *att;
+    picture_pool_t *pool; /* picture pool */
+    picture_resource_t resource[MAX_PICTURES];
+};
 
-    err = xcb_request_check (vout->p_sys->conn, ck);
-    if (err)
-    {
-        msg_Err (vout, "%s: X11 error %d", str, err->error_code);
-        return VLC_EGENERIC;
-    }
-    return VLC_SUCCESS;
-}
+static picture_t *Get (vout_display_t *);
+static void Display (vout_display_t *, picture_t *);
+static int Control (vout_display_t *, int, va_list);
+static void Manage (vout_display_t *);
 
 /**
  * Check that the X server supports the XVideo extension.
  */
-static bool CheckXVideo (vout_thread_t *vout, xcb_connection_t *conn)
+static bool CheckXVideo (vout_display_t *vd, xcb_connection_t *conn)
 {
     xcb_xv_query_extension_reply_t *r;
     xcb_xv_query_extension_cookie_t ck = xcb_xv_query_extension (conn);
@@ -116,129 +108,21 @@ static bool CheckXVideo (vout_thread_t *vout, xcb_connection_t *conn)
     {   /* We need XVideo 2.2 for PutImage */
         if ((r->major > 2) || (r->major == 2 && r->minor >= 2))
         {
-            msg_Dbg (vout, "using XVideo extension v%"PRIu8".%"PRIu8,
+            msg_Dbg (vd, "using XVideo extension v%"PRIu8".%"PRIu8,
                      r->major, r->minor);
             ok = true;
         }
         else
-            msg_Dbg (vout, "XVideo extension too old (v%"PRIu8".%"PRIu8,
+            msg_Dbg (vd, "XVideo extension too old (v%"PRIu8".%"PRIu8,
                      r->major, r->minor);
         free (r);
     }
     else
-        msg_Dbg (vout, "XVideo extension not available");
+        msg_Dbg (vd, "XVideo extension not available");
     return ok;
 }
 
-/**
- * Get a list of XVideo adaptors for a given window.
- */
-static xcb_xv_query_adaptors_reply_t *GetAdaptors (vout_window_t *wnd,
-                                                   xcb_connection_t *conn)
-{
-    xcb_xv_query_adaptors_cookie_t ck;
-
-    ck = xcb_xv_query_adaptors (conn, wnd->handle.xid);
-    return xcb_xv_query_adaptors_reply (conn, ck, NULL);
-}
-
-#define p_vout vout
-
-/**
- * Probe the X server.
- */
-static int Open (vlc_object_t *obj)
-{
-    vout_thread_t *vout = (vout_thread_t *)obj;
-    vout_sys_t *p_sys = malloc (sizeof (*p_sys));
-    if (p_sys == NULL)
-        return VLC_ENOMEM;
-
-    vout->p_sys = p_sys;
-
-    /* Connect to X */
-    p_sys->conn = Connect (obj);
-    if (p_sys->conn == NULL)
-    {
-        free (p_sys);
-        return VLC_EGENERIC;
-    }
-
-    if (!CheckXVideo (vout, p_sys->conn))
-    {
-        msg_Warn (vout, "Please enable XVideo 2.2 for faster video display");
-        xcb_disconnect (p_sys->conn);
-        free (p_sys);
-        return VLC_EGENERIC;
-    }
-
-    const xcb_screen_t *screen;
-    p_sys->embed = GetWindow (vout, p_sys->conn, &screen, &p_sys->shm);
-    if (p_sys->embed == NULL)
-    {
-        xcb_disconnect (p_sys->conn);
-        free (p_sys);
-        return VLC_EGENERIC;
-    }
-
-    /* Cache adaptors infos */
-    p_sys->adaptors = GetAdaptors (p_sys->embed, p_sys->conn);
-    if (p_sys->adaptors == NULL)
-        goto error;
-
-    /* Create window */
-    {
-        const uint32_t mask =
-            /* XCB_CW_EVENT_MASK */
-            XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE |
-            XCB_EVENT_MASK_POINTER_MOTION;
-        xcb_void_cookie_t c;
-        xcb_window_t window = xcb_generate_id (p_sys->conn);
-
-        c = xcb_create_window_checked (p_sys->conn, screen->root_depth, window,
-                                       p_sys->embed->handle.xid, 0, 0, 1, 1, 0,
-                                       XCB_WINDOW_CLASS_INPUT_OUTPUT,
-                                       screen->root_visual,
-                                       XCB_CW_EVENT_MASK, &mask);
-        if (CheckError (vout, "cannot create X11 window", c))
-            goto error;
-        p_sys->window = window;
-        msg_Dbg (vout, "using X11 window %08"PRIx32, p_sys->window);
-        xcb_map_window (p_sys->conn, window);
-    }
-
-    p_sys->gc = xcb_generate_id (p_sys->conn);
-    xcb_create_gc (p_sys->conn, p_sys->gc, p_sys->window, 0, NULL);
-    msg_Dbg (vout, "using X11 graphic context %08"PRIx32, p_sys->gc);
-
-    vout->pf_init = Init;
-    vout->pf_end = Deinit;
-    vout->pf_display = Display;
-    vout->pf_manage = Manage;
-    vout->pf_control = Control;
-    return VLC_SUCCESS;
-
-error:
-    Close (obj);
-    return VLC_EGENERIC;
-}
-
-
-/**
- * Disconnect from the X server.
- */
-static void Close (vlc_object_t *obj)
-{
-    vout_thread_t *vout = (vout_thread_t *)obj;
-    vout_sys_t *p_sys = vout->p_sys;
-
-    free (p_sys->adaptors);
-    vout_window_Delete (p_sys->embed);
-    xcb_disconnect (p_sys->conn);
-    free (p_sys);
-}
-
-static vlc_fourcc_t ParseFormat (vout_thread_t *vout,
+static vlc_fourcc_t ParseFormat (vout_display_t *vd,
                                  const xcb_xv_image_format_info_t *restrict f)
 {
     if (f->byte_order != ORDER && f->bpp != 8)
@@ -273,9 +157,9 @@ static vlc_fourcc_t ParseFormat (vout_thread_t *vout,
             }
             break;
         }
-        msg_Err (vout, "unknown XVideo RGB format %"PRIx32" (%.4s)",
+        msg_Err (vd, "unknown XVideo RGB format %"PRIx32" (%.4s)",
                  f->id, f->guid);
-        msg_Dbg (vout, " %"PRIu8" planes, %"PRIu8" bits/pixel, "
+        msg_Dbg (vd, " %"PRIu8" planes, %"PRIu8" bits/pixel, "
                  "depth %"PRIu8, f->num_planes, f->bpp, f->depth);
         break;
 
@@ -321,16 +205,16 @@ static vlc_fourcc_t ParseFormat (vout_thread_t *vout,
             break;
         }
     bad:
-        msg_Err (vout, "unknown XVideo YUV format %"PRIx32" (%.4s)", f->id,
+        msg_Err (vd, "unknown XVideo YUV format %"PRIx32" (%.4s)", f->id,
                  f->guid);
-        msg_Dbg (vout, " %"PRIu8" planes, %"PRIu32" bits/pixel, "
+        msg_Dbg (vd, " %"PRIu8" planes, %"PRIu32" bits/pixel, "
                  "%"PRIu32"/%"PRIu32"/%"PRIu32" bits/sample", f->num_planes,
                  f->bpp, f->y_sample_bits, f->u_sample_bits, f->v_sample_bits);
-        msg_Dbg (vout, " period: %"PRIu32"/%"PRIu32"/%"PRIu32"x"
+        msg_Dbg (vd, " period: %"PRIu32"/%"PRIu32"/%"PRIu32"x"
                  "%"PRIu32"/%"PRIu32"/%"PRIu32,
                  f->vhorz_y_period, f->vhorz_u_period, f->vhorz_v_period,
                  f->vvert_y_period, f->vvert_u_period, f->vvert_v_period);
-        msg_Warn (vout, " order: %.32s", f->vcomp_order);
+        msg_Warn (vd, " order: %.32s", f->vcomp_order);
         break;
     }
     return 0;
@@ -338,11 +222,13 @@ static vlc_fourcc_t ParseFormat (vout_thread_t *vout,
 
 
 static const xcb_xv_image_format_info_t *
-FindFormat (vout_thread_t *vout, vlc_fourcc_t chroma, xcb_xv_port_t port,
+FindFormat (vout_display_t *vd,
+            vlc_fourcc_t chroma, const video_format_t *fmt,
+            xcb_xv_port_t port,
             const xcb_xv_list_image_formats_reply_t *list,
             xcb_xv_query_image_attributes_reply_t **restrict pa)
 {
-    xcb_connection_t *conn = vout->p_sys->conn;
+    xcb_connection_t *conn = vd->sys->conn;
     const xcb_xv_image_format_info_t *f, *end;
 
 #ifndef XCB_XV_OLD
@@ -353,21 +239,21 @@ FindFormat (vout_thread_t *vout, vlc_fourcc_t chroma, xcb_xv_port_t port,
     end = f + xcb_xv_list_image_formats_format_length (list);
     for (; f < end; f++)
     {
-        if (chroma != ParseFormat (vout, f))
+        if (chroma != ParseFormat (vd, f))
             continue;
 
         xcb_xv_query_image_attributes_reply_t *i;
         i = xcb_xv_query_image_attributes_reply (conn,
             xcb_xv_query_image_attributes (conn, port, f->id,
-                vout->fmt_in.i_width, vout->fmt_in.i_height), NULL);
+                fmt->i_width, fmt->i_height), NULL);
         if (i == NULL)
             continue;
 
-        if (i->width != vout->fmt_in.i_width
-         || i->height != vout->fmt_in.i_height)
+        if (i->width != fmt->i_width
+         || i->height != fmt->i_height)
         {
-            msg_Warn (vout, "incompatible size %ux%u -> %"PRIu32"x%"PRIu32,
-                      vout->fmt_in.i_width, vout->fmt_in.i_height,
+            msg_Warn (vd, "incompatible size %ux%u -> %"PRIu32"x%"PRIu32,
+                      fmt->i_width, fmt->i_height,
                       i->width, i->height);
             free (i);
             continue;
@@ -378,14 +264,67 @@ FindFormat (vout_thread_t *vout, vlc_fourcc_t chroma, xcb_xv_port_t port,
     return NULL;
 }
 
+
 /**
- * Allocate drawable window and picture buffers.
+ * Get a list of XVideo adaptors for a given window.
  */
-static int Init (vout_thread_t *vout)
+static xcb_xv_query_adaptors_reply_t *GetAdaptors (vout_window_t *wnd,
+                                                   xcb_connection_t *conn)
 {
-    vout_sys_t *p_sys = vout->p_sys;
-    xcb_xv_query_image_attributes_reply_t *att = NULL;
-    bool swap_planes = false; /* whether X wants V before U */
+    xcb_xv_query_adaptors_cookie_t ck;
+
+    ck = xcb_xv_query_adaptors (conn, wnd->handle.xid);
+    return xcb_xv_query_adaptors_reply (conn, ck, NULL);
+}
+
+/**
+ * Probe the X server.
+ */
+static int Open (vlc_object_t *obj)
+{
+    vout_display_t *vd = (vout_display_t *)obj;
+    vout_display_sys_t *p_sys = malloc (sizeof (*p_sys));
+    if (p_sys == NULL)
+        return VLC_ENOMEM;
+
+    vd->sys = p_sys;
+
+    /* Connect to X */
+    p_sys->conn = Connect (obj);
+    if (p_sys->conn == NULL)
+    {
+        free (p_sys);
+        return VLC_EGENERIC;
+    }
+
+    if (!CheckXVideo (vd, p_sys->conn))
+    {
+        msg_Warn (vd, "Please enable XVideo 2.2 for faster video display");
+        xcb_disconnect (p_sys->conn);
+        free (p_sys);
+        return VLC_EGENERIC;
+    }
+
+    const xcb_screen_t *screen;
+    p_sys->embed = GetWindow (vd, p_sys->conn, &screen, &p_sys->shm);
+    if (p_sys->embed == NULL)
+    {
+        xcb_disconnect (p_sys->conn);
+        free (p_sys);
+        return VLC_EGENERIC;
+    }
+
+    /* Cache adaptors infos */
+    p_sys->adaptors = GetAdaptors (p_sys->embed, p_sys->conn);
+    if (p_sys->adaptors == NULL)
+        goto error;
+
+    /* */
+    video_format_t fmt = vd->fmt;
+    // TODO !
+#if 1
+    p_sys->att = NULL;
+    bool found_adaptor = false;
 
     /* FIXME: check max image size */
     xcb_xv_adaptor_info_iterator_t it;
@@ -405,11 +344,11 @@ static int Init (vout_thread_t *vout)
         if (r == NULL)
             continue;
 
-        const xcb_xv_image_format_info_t *fmt;
+        const xcb_xv_image_format_info_t *xfmt;
 
         /* Video chroma in preference order */
         const vlc_fourcc_t chromas[] = {
-            vout->fmt_in.i_chroma,
+            fmt.i_chroma,
             VLC_CODEC_YUYV,
             VLC_CODEC_RGB24,
             VLC_CODEC_RGB15,
@@ -417,10 +356,10 @@ static int Init (vout_thread_t *vout)
         for (size_t i = 0; i < sizeof (chromas) / sizeof (chromas[0]); i++)
         {
             vlc_fourcc_t chroma = chromas[i];
-            fmt = FindFormat (vout, chroma, a->base_id, r, &att);
-            if (fmt != NULL)
+            xfmt = FindFormat (vd, chroma, &fmt, a->base_id, r, &p_sys->att);
+            if (xfmt != NULL)
             {
-                vout->output.i_chroma = chroma;
+                fmt.i_chroma = chroma;
                 goto found_format;
             }
         }
@@ -430,203 +369,306 @@ static int Init (vout_thread_t *vout)
     found_format:
         /* TODO: grab port */
         p_sys->port = a->base_id;
-        msg_Dbg (vout, "using port %"PRIu32, p_sys->port);
+        msg_Dbg (vd, "using port %"PRIu32, p_sys->port);
 
-        p_sys->id = fmt->id;
-        msg_Dbg (vout, "using image format 0x%"PRIx32, p_sys->id);
-        if (fmt->type == XCB_XV_IMAGE_FORMAT_INFO_TYPE_RGB)
+        p_sys->id = xfmt->id;
+        msg_Dbg (vd, "using image format 0x%"PRIx32, p_sys->id);
+        if (xfmt->type == XCB_XV_IMAGE_FORMAT_INFO_TYPE_RGB)
         {
-            vout->fmt_out.i_rmask = vout->output.i_rmask = fmt->red_mask;
-            vout->fmt_out.i_gmask = vout->output.i_gmask = fmt->green_mask;
-            vout->fmt_out.i_bmask = vout->output.i_bmask = fmt->blue_mask;
+            fmt.i_rmask = xfmt->red_mask;
+            fmt.i_gmask = xfmt->green_mask;
+            fmt.i_bmask = xfmt->blue_mask;
         }
         else
-        if (fmt->num_planes == 3)
-            swap_planes = !strcmp ((const char *)fmt->vcomp_order, "YVU");
+        if (xfmt->num_planes == 3
+         && !strcmp ((const char *)xfmt->vcomp_order, "YVU"))
+            fmt.i_chroma = VLC_CODEC_YV12;
         free (r);
-        goto found_adaptor;
+        found_adaptor = true;
+        break;
     }
-    msg_Err (vout, "no available XVideo adaptor");
-    return VLC_EGENERIC; /* no usable adaptor */
-
-    /* Allocate picture buffers */
-    const uint32_t *offsets;
-found_adaptor:
-    offsets = xcb_xv_query_image_attributes_offsets (att);
-    p_sys->data_size = att->data_size;
+    if (!found_adaptor)
+    {
+        msg_Err (vd, "no available XVideo adaptor");
+        goto error;
+    }
+#endif
 
-    I_OUTPUTPICTURES = 0;
-    for (size_t index = 0; I_OUTPUTPICTURES < 2; index++)
+    /* Create window */
     {
-        picture_t *pic = vout->p_picture + index;
+        const uint32_t mask =
+            /* XCB_CW_EVENT_MASK */
+            XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE |
+            XCB_EVENT_MASK_POINTER_MOTION;
+        xcb_void_cookie_t c;
+        xcb_window_t window = xcb_generate_id (p_sys->conn);
 
-        if (index > sizeof (vout->p_picture) / sizeof (pic))
-            break;
-        if (pic->i_status != FREE_PICTURE)
-            continue;
+        c = xcb_create_window_checked (p_sys->conn, screen->root_depth, window,
+                                       p_sys->embed->handle.xid, 0, 0, 1, 1, 0,
+                                       XCB_WINDOW_CLASS_INPUT_OUTPUT,
+                                       screen->root_visual,
+                                       XCB_CW_EVENT_MASK, &mask);
+        if (CheckError (vd, p_sys->conn, "cannot create X11 window", c))
+            goto error;
+        p_sys->window = window;
+        msg_Dbg (vd, "using X11 window %08"PRIx32, p_sys->window);
+        xcb_map_window (p_sys->conn, window);
 
-        picture_Setup (pic, vout->output.i_chroma,
-                       att->width, att->height,
-                       vout->fmt_in.i_aspect);
-        if (PictureAlloc (vout, pic, att->data_size,
-                          p_sys->shm ? p_sys->conn : NULL))
-            break;
-        /* Allocate further planes as specified by XVideo */
-        /* We assume that offsets[0] is zero */
-        for (int i = 1; i < pic->i_planes; i++)
-             pic->p[i].p_pixels =
-                 pic->p->p_pixels + offsets[swap_planes ? (3 - i) : i];
-        PP_OUTPUTPICTURE[I_OUTPUTPICTURES++] = pic;
+        vout_display_place_t place;
+
+        vout_display_PlacePicture (&place, &vd->source, vd->cfg, false);
+        p_sys->width  = place.width;
+        p_sys->height = place.height;
+
+        /* */
+        const uint32_t values[] = { place.x, place.y, place.width, place.height };
+        xcb_configure_window (p_sys->conn, p_sys->window,
+                              XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y |
+                              XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
+                              values);
     }
-    free (att);
 
-    unsigned x, y, width, height;
+    /* Create graphic context */
+    p_sys->gc = xcb_generate_id (p_sys->conn);
+    xcb_create_gc (p_sys->conn, p_sys->gc, p_sys->window, 0, NULL);
+    msg_Dbg (vd, "using X11 graphic context %08"PRIx32, p_sys->gc);
 
-    if (GetWindowSize (p_sys->embed, p_sys->conn, &width, &height))
-        return VLC_EGENERIC;
-    vout_PlacePicture (vout, width, height, &x, &y, &width, &height);
+    /* */
+    p_sys->pool = NULL;
 
-    const uint32_t values[] = { x, y, width, height, };
-    xcb_configure_window (p_sys->conn, p_sys->window,
-                          XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y |
-                          XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
-                          values);
-    xcb_flush (p_sys->conn);
-    p_sys->height = height;
-    p_sys->width = width;
+    /* */
+    vout_display_info_t info = vd->info;
+    info.has_pictures_invalid = false;
 
-    vout->fmt_out.i_chroma = vout->output.i_chroma;
-    vout->fmt_out.i_visible_width = vout->fmt_in.i_visible_width;
-    vout->fmt_out.i_visible_height = vout->fmt_in.i_visible_height;
-    vout->fmt_out.i_sar_num = vout->fmt_out.i_sar_den = 1;
+    /* Setup vout_display_t once everything is fine */
+    vd->fmt = fmt;
+    vd->info = info;
 
-    vout->output.i_width = vout->fmt_out.i_width = vout->fmt_in.i_width;
-    vout->output.i_height = vout->fmt_out.i_height = vout->fmt_in.i_height;
-    vout->fmt_out.i_x_offset = vout->fmt_in.i_x_offset;
-    vout->fmt_out.i_y_offset = vout->fmt_in.i_y_offset;
+    vd->get = Get;
+    vd->prepare = NULL;
+    vd->display = Display;
+    vd->control = Control;
+    vd->manage = Manage;
 
-    assert (height > 0);
-    vout->output.i_aspect = vout->fmt_out.i_aspect =
-        width * VOUT_ASPECT_FACTOR / height;
+    /* */
+    unsigned width, height;
+    if (!GetWindowSize (p_sys->embed, p_sys->conn, &width, &height))
+        vout_display_SendEventDisplaySize (vd, width, height);
+    vout_display_SendEventFullscreen (vd, false);
 
     return VLC_SUCCESS;
+
+error:
+    Close (obj);
+    return VLC_EGENERIC;
+}
+
+
+/**
+ * Disconnect from the X server.
+ */
+static void Close (vlc_object_t *obj)
+{
+    vout_display_t *vd = (vout_display_t *)obj;
+    vout_display_sys_t *p_sys = vd->sys;
+
+    if (p_sys->pool)
+    {
+        for (unsigned i = 0; i < MAX_PICTURES; i++)
+        {
+            picture_resource_t *res = &p_sys->resource[i];
+
+            if (!res->p->p_pixels)
+                break;
+            PictureResourceFree (res, p_sys->conn);
+        }
+        picture_pool_Delete (p_sys->pool);
+    }
+
+    free (p_sys->att);
+    free (p_sys->adaptors);
+    vout_display_DeleteWindow (vd, p_sys->embed);
+    xcb_disconnect (p_sys->conn);
+    free (p_sys);
 }
 
 /**
- * Free picture buffers.
+ * Return a direct buffer
  */
-static void Deinit (vout_thread_t *vout)
+static picture_t *Get (vout_display_t *vd)
 {
-    vout_sys_t *p_sys = vout->p_sys;
+    vout_display_sys_t *p_sys = vd->sys;
+
+    if (!p_sys->pool)
+    {
+        picture_t *pic = picture_New (vd->fmt.i_chroma,
+                                      p_sys->att->width, p_sys->att->height, 0);
+        if (!pic)
+            return NULL;
+
+        memset (p_sys->resource, 0, sizeof(p_sys->resource));
+
+        const uint32_t *offsets =
+            xcb_xv_query_image_attributes_offsets (p_sys->att);
+        p_sys->data_size = p_sys->att->data_size;
+
+        unsigned count;
+        picture_t *pic_array[MAX_PICTURES];
+        for (count = 0; count < MAX_PICTURES; count++)
+        {
+            picture_resource_t *res = &p_sys->resource[count];
+
+            for (int i = 0; i < pic->i_planes; i++)
+            {
+                res->p[i].i_lines = pic->p[i].i_lines; /* FIXME seems wrong*/
+                res->p[i].i_pitch = pic->p[i].i_pitch;
+            }
+            if (PictureResourceAlloc (vd, res, p_sys->att->data_size,
+                                      p_sys->conn, p_sys->shm))
+                break;
+
+            /* Allocate further planes as specified by XVideo */
+            /* We assume that offsets[0] is zero */
+            for (int i = 1; i < pic->i_planes; i++)
+                res->p[i].p_pixels = res->p[0].p_pixels + offsets[i];
+            pic_array[count] = picture_NewFromResource (&vd->fmt, res);
+            if (!pic_array[count])
+            {
+                PictureResourceFree (res, p_sys->conn);
+                memset (res, 0, sizeof(*res));
+                break;
+            }
+        }
+        picture_Release (pic);
+
+        if (count == 0)
+            return NULL;
+
+        p_sys->pool = picture_pool_New (count, pic_array);
+        if (!p_sys->pool)
+        {
+            /* TODO release picture resources */
+            return NULL;
+        }
+        /* FIXME should also do it in case of error ? */
+        xcb_flush (p_sys->conn);
+    }
 
-    for (int i = 0; i < I_OUTPUTPICTURES; i++)
-        PictureFree (PP_OUTPUTPICTURE[i], p_sys->conn);
+    return picture_pool_Get (p_sys->pool);
 }
 
 /**
  * Sends an image to the X server.
  */
-static void Display (vout_thread_t *vout, picture_t *pic)
+static void Display (vout_display_t *vd, picture_t *pic)
 {
-    vout_sys_t *p_sys = vout->p_sys;
-    xcb_shm_seg_t segment = (uintptr_t)pic->p_sys;
+    vout_display_sys_t *p_sys = vd->sys;
+    xcb_shm_seg_t segment = pic->p_sys->segment;
 
     if (segment)
         xcb_xv_shm_put_image (p_sys->conn, p_sys->port, p_sys->window,
                               p_sys->gc, segment, p_sys->id, 0,
-                              /* Src: */ vout->fmt_out.i_x_offset,
-                              vout->fmt_out.i_y_offset,
-                              vout->fmt_out.i_visible_width,
-                              vout->fmt_out.i_visible_height,
-                              /* Dst: */ 0, 0, p_sys->width, p_sys->height,
-                              /* Memory: */
-                              pic->p->i_pitch / pic->p->i_pixel_pitch,
+                   /* Src: */ vd->source.i_x_offset,
+                              vd->source.i_y_offset,
+                              vd->source.i_visible_width,
+                              vd->source.i_visible_height,
+                   /* Dst: */ 0, 0, p_sys->width, p_sys->height,
+                /* Memory: */ pic->p->i_pitch / pic->p->i_pixel_pitch,
                               pic->p->i_lines, false);
     else
         xcb_xv_put_image (p_sys->conn, p_sys->port, p_sys->window,
                           p_sys->gc, p_sys->id,
-                          vout->fmt_out.i_x_offset, vout->fmt_out.i_y_offset,
-                          vout->fmt_out.i_visible_width,
-                          vout->fmt_out.i_visible_height,
+                          vd->source.i_x_offset,
+                          vd->source.i_y_offset,
+                          vd->source.i_visible_width,
+                          vd->source.i_visible_height,
                           0, 0, p_sys->width, p_sys->height,
-                          vout->fmt_out.i_width, vout->fmt_out.i_height,
+                          vd->source.i_width, vd->source.i_height,
                           p_sys->data_size, pic->p->p_pixels);
+
     xcb_flush (p_sys->conn);
+    picture_Release (pic);
 }
 
-/**
- * Process incoming X events.
- */
-static int Manage (vout_thread_t *vout)
+static int Control (vout_display_t *vd, int query, va_list ap)
 {
-    vout_sys_t *p_sys = vout->p_sys;
-    xcb_generic_event_t *ev;
+    vout_display_sys_t *p_sys = vd->sys;
 
-    while ((ev = xcb_poll_for_event (p_sys->conn)) != NULL)
-        ProcessEvent (vout, p_sys->conn, p_sys->window, ev);
-
-    if (xcb_connection_has_error (p_sys->conn))
+    switch (query)
     {
-        msg_Err (vout, "X server failure");
-        return VLC_EGENERIC;
-    }
+    case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
+    case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
+    case VOUT_DISPLAY_CHANGE_ZOOM:
+    case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
+    case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
+    {
+        const vout_display_cfg_t *cfg;
+        const video_format_t *source;
 
-    CommonManage (vout);
-    if (vout->i_changes & VOUT_SIZE_CHANGE)
-    {   /* TODO: factor this code with XV and X11 Init() */
-        unsigned x, y, width, height;
+        if (query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT
+         || query == VOUT_DISPLAY_CHANGE_SOURCE_CROP)
+        {
+            source = (const video_format_t *)va_arg (ap, const video_format_t *);
+            cfg = vd->cfg;
+        }
+        else
+        {
+            source = &vd->source;
+            cfg = (const vout_display_cfg_t*)va_arg (ap, const vout_display_cfg_t *);
+        }
 
-        if (GetWindowSize (p_sys->embed, p_sys->conn, &width, &height))
+        /* */
+        if (query == VOUT_DISPLAY_CHANGE_DISPLAY_SIZE
+         && (cfg->display.width  != vd->cfg->display.width
+           ||cfg->display.height != vd->cfg->display.height)
+         && vout_window_SetSize (p_sys->embed,
+                                  cfg->display.width,
+                                  cfg->display.height))
             return VLC_EGENERIC;
-        vout_PlacePicture (vout, width, height, &x, &y, &width, &height);
-
-        const uint32_t values[] = { x, y, width, height, };
-        xcb_configure_window (p_sys->conn, p_sys->window, XCB_CONFIG_WINDOW_X |
-                              XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH |
-                              XCB_CONFIG_WINDOW_HEIGHT, values);
-        vout->p_sys->width = width; // XXX: <-- this is useless, as the zoom is
-        vout->p_sys->height = height; // handled with VOUT_SET_SIZE anyway.
-        vout->i_changes &= ~VOUT_SIZE_CHANGE;
-    }
-    return VLC_SUCCESS;
-}
-
-void
-HandleParentStructure (vout_thread_t *vout, xcb_connection_t *conn,
-                       xcb_window_t xid, xcb_configure_notify_event_t *ev)
-{
-    unsigned width, height, x, y;
-
-    vout_PlacePicture (vout, ev->width, ev->height, &x, &y, &width, &height);
-
-    /* Move the picture within the window */
-    const uint32_t values[] = { x, y, width, height, };
-    xcb_configure_window (conn, xid,
-                          XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y
-                        | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
-                          values);
-    vout->p_sys->width = width;
-    vout->p_sys->height = height;
-}
 
-static int Control (vout_thread_t *vout, int query, va_list ap)
-{
-    /* FIXME it can be shared between x11 and xvideo */
-    switch (query)
-    {
-    case VOUT_SET_SIZE:
-    {
-        const unsigned width  = va_arg (ap, unsigned);
-        const unsigned height = va_arg (ap, unsigned);
-        return vout_window_SetSize (vout->p_sys->embed, width, height);
+        vout_display_place_t place;
+        vout_display_PlacePicture (&place, source, cfg, false);
+        p_sys->width  = place.width;
+        p_sys->height = place.height;
+
+        /* Move the picture within the window */
+        const uint32_t values[] = { place.x, place.y,
+                                    place.width, place.height, };
+        xcb_configure_window (p_sys->conn, p_sys->window,
+                              XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y
+                            | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
+                              values);
+        xcb_flush (p_sys->conn);
+        return VLC_SUCCESS;
     }
-    case VOUT_SET_STAY_ON_TOP:
+    case VOUT_DISPLAY_CHANGE_ON_TOP:
     {
-        const bool is_on_top = va_arg (ap, int);
-        return vout_window_SetOnTop (vout->p_sys->embed, is_on_top);
+        int on_top = (int)va_arg (ap, int);
+        return vout_window_SetOnTop (p_sys->embed, on_top);
     }
+
+    /* TODO */
+#if 0
+    /* Hide the mouse. It will be send when
+     * vout_display_t::info.b_hide_mouse is false */
+    VOUT_DISPLAY_HIDE_MOUSE,
+
+    /* Ask the module to acknowledge/refuse the fullscreen state change after
+     * being requested (externaly or by VOUT_DISPLAY_EVENT_FULLSCREEN */
+    VOUT_DISPLAY_CHANGE_FULLSCREEN,     /* const vout_display_cfg_t *p_cfg */
+#endif
+    case VOUT_DISPLAY_RESET_PICTURES:
+        assert(0);
     default:
+        msg_Err (vd, "Unknown request in XCB vout display");
         return VLC_EGENERIC;
     }
+}
 
+static void Manage (vout_display_t *vd)
+{
+    vout_display_sys_t *p_sys = vd->sys;
+
+    ManageEvent (vd, p_sys->conn, p_sys->window);
 }
+