3 * @brief Common code for XCB video output plugins
5 /*****************************************************************************
6 * Copyright © 2009 Rémi Denis-Courmont
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 ****************************************************************************/
30 #include <sys/types.h>
36 #include <vlc_common.h>
37 #include <vlc_vout_display.h>
42 * Connect to the X server.
44 static xcb_connection_t *Connect (vlc_object_t *obj, const char *display)
46 xcb_connection_t *conn = xcb_connect (display, NULL);
47 if (xcb_connection_has_error (conn) /*== NULL*/)
49 msg_Err (obj, "cannot connect to X server (%s)",
50 display ? display : "default");
51 xcb_disconnect (conn);
55 const xcb_setup_t *setup = xcb_get_setup (conn);
56 msg_Dbg (obj, "connected to X%"PRIu16".%"PRIu16" server",
57 setup->protocol_major_version, setup->protocol_minor_version);
58 char *vendor = strndup (xcb_setup_vendor (setup), setup->vendor_len);
61 msg_Dbg (obj, " vendor : %s", vendor);
64 msg_Dbg (obj, " version: %"PRIu32, setup->release_number);
69 * Find screen matching a given root window.
71 static const xcb_screen_t *FindScreen (vlc_object_t *obj,
72 xcb_connection_t *conn,
75 /* Find the selected screen */
76 const xcb_setup_t *setup = xcb_get_setup (conn);
77 const xcb_screen_t *screen = NULL;
78 for (xcb_screen_iterator_t i = xcb_setup_roots_iterator (setup);
79 i.rem > 0 && screen == NULL; xcb_screen_next (&i))
81 if (i.data->root == root)
87 msg_Err (obj, "parent window screen not found");
90 msg_Dbg (obj, "using screen 0x%"PRIx32, root);
94 static const xcb_screen_t *FindWindow (vlc_object_t *obj,
95 xcb_connection_t *conn,
97 uint8_t *restrict pdepth)
99 xcb_get_geometry_reply_t *geo =
100 xcb_get_geometry_reply (conn, xcb_get_geometry (conn, xid), NULL);
103 msg_Err (obj, "parent window not valid");
107 const xcb_screen_t *screen = FindScreen (obj, conn, geo->root);
108 *pdepth = geo->depth;
115 * Create a VLC video X window object, connect to the corresponding X server,
116 * find the corresponding X server screen.
118 vout_window_t *GetWindow (vout_display_t *vd,
119 xcb_connection_t **restrict pconn,
120 const xcb_screen_t **restrict pscreen,
121 uint8_t *restrict pdepth)
124 vout_window_cfg_t wnd_cfg;
126 memset( &wnd_cfg, 0, sizeof(wnd_cfg) );
127 wnd_cfg.type = VOUT_WINDOW_TYPE_XID;
128 wnd_cfg.width = vd->cfg->display.width;
129 wnd_cfg.height = vd->cfg->display.height;
131 vout_window_t *wnd = vout_display_NewWindow (vd, &wnd_cfg);
134 msg_Err (vd, "parent window not available");
138 xcb_connection_t *conn = Connect (VLC_OBJECT(vd), wnd->x11_display);
143 *pscreen = FindWindow (VLC_OBJECT(vd), conn, wnd->xid, pdepth);
144 if (*pscreen == NULL)
146 xcb_disconnect (conn);
150 RegisterMouseEvents (VLC_OBJECT(vd), conn, wnd->xid);
154 vout_display_DeleteWindow (vd, wnd);
158 /** Check MIT-SHM shared memory support */
159 void CheckSHM (vlc_object_t *obj, xcb_connection_t *conn, bool *restrict pshm)
161 bool shm = var_CreateGetBool (obj, "x11-shm") > 0;
164 xcb_shm_query_version_cookie_t ck;
165 xcb_shm_query_version_reply_t *r;
167 ck = xcb_shm_query_version (conn);
168 r = xcb_shm_query_version_reply (conn, ck, NULL);
171 msg_Err (obj, "shared memory (MIT-SHM) not available");
172 msg_Warn (obj, "display will be slow");
181 * Initialize a picture buffer as shared memory, according to the video output
182 * format. If a attach is true, the segment is attached to
183 * the X server (MIT-SHM extension).
185 int PictureResourceAlloc (vout_display_t *vd, picture_resource_t *res, size_t size,
186 xcb_connection_t *conn, bool attach)
188 res->p_sys = malloc (sizeof(*res->p_sys));
192 /* Allocate shared memory segment */
193 int id = shmget (IPC_PRIVATE, size, IPC_CREAT | 0700);
196 msg_Err (vd, "shared memory allocation error: %m");
201 /* Attach the segment to VLC */
202 void *shm = shmat (id, NULL, 0 /* read/write */);
203 if (-1 == (intptr_t)shm)
205 msg_Err (vd, "shared memory attachment error: %m");
206 shmctl (id, IPC_RMID, 0);
211 xcb_shm_seg_t segment;
214 /* Attach the segment to X */
215 xcb_void_cookie_t ck;
217 segment = xcb_generate_id (conn);
218 ck = xcb_shm_attach_checked (conn, segment, id, 1);
220 if (CheckError (vd, conn, "shared memory server-side error", ck))
222 msg_Info (vd, "using buggy X11 server - SSH proxying?");
229 shmctl (id, IPC_RMID, 0);
230 res->p_sys->segment = segment;
231 res->p->p_pixels = shm;
236 * Release picture private data: detach the shared memory segment.
238 void PictureResourceFree (picture_resource_t *res, xcb_connection_t *conn)
240 xcb_shm_seg_t segment = res->p_sys->segment;
242 if (conn != NULL && segment != 0)
243 xcb_shm_detach (conn, segment);
244 shmdt (res->p->p_pixels);