X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_output%2Fxcb%2Fcommon.c;h=2b7588f319823000e67de25369f357ef35b912ed;hb=HEAD;hp=6bfac3f28de67b9fdd2f3c4fa9750f27586a3e9c;hpb=18ed9eea8920f43ba53a0910a57269b0444b1841;p=vlc diff --git a/modules/video_output/xcb/common.c b/modules/video_output/xcb/common.c index 6bfac3f28d..2b7588f319 100644 --- a/modules/video_output/xcb/common.c +++ b/modules/video_output/xcb/common.c @@ -7,7 +7,7 @@ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2.0 + * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, @@ -15,7 +15,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public + * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ****************************************************************************/ @@ -34,72 +34,47 @@ #include #include -#include -#include +#include #include "xcb_vlc.h" /** * Connect to the X server. */ -xcb_connection_t *Connect (vlc_object_t *obj) +static xcb_connection_t *Connect (vlc_object_t *obj, const char *display) { - char *display = var_CreateGetNonEmptyString (obj, "x11-display"); xcb_connection_t *conn = xcb_connect (display, NULL); - - free (display); if (xcb_connection_has_error (conn) /*== NULL*/) { - msg_Err (obj, "cannot connect to X server"); + msg_Err (obj, "cannot connect to X server (%s)", + display ? display : "default"); xcb_disconnect (conn); return NULL; } + + const xcb_setup_t *setup = xcb_get_setup (conn); + msg_Dbg (obj, "connected to X%"PRIu16".%"PRIu16" server", + setup->protocol_major_version, setup->protocol_minor_version); + char *vendor = strndup (xcb_setup_vendor (setup), setup->vendor_len); + if (vendor) + { + msg_Dbg (obj, " vendor : %s", vendor); + free (vendor); + } + msg_Dbg (obj, " version: %"PRIu32, setup->release_number); return conn; } - /** - * Create a VLC video X window object, find the corresponding X server screen, - * and probe the MIT-SHM extension. + * Find screen matching a given root window. */ -vout_window_t *GetWindow (vout_thread_t *obj, - xcb_connection_t *conn, - const xcb_screen_t **restrict pscreen, - bool *restrict pshm) +static const xcb_screen_t *FindScreen (vlc_object_t *obj, + xcb_connection_t *conn, + xcb_window_t root) { - /* Get window */ - xcb_window_t root; - vout_window_t *wnd = vout_RequestXWindow (obj, &(int){ 0 }, &(int){ 0 }, - &(unsigned){ 0 }, &(unsigned){ 0 }); - if (wnd == NULL) - { - msg_Err (obj, "parent window not available"); - return NULL; - } - else - { - xcb_get_geometry_reply_t *geo; - xcb_get_geometry_cookie_t ck; - - ck = xcb_get_geometry (conn, wnd->handle.xid); - geo = xcb_get_geometry_reply (conn, ck, NULL); - if (geo == NULL) - { - msg_Err (obj, "parent window not valid"); - goto error; - } - root = geo->root; - free (geo); - - /* Subscribe to parent window resize events */ - const uint32_t value = XCB_EVENT_MASK_STRUCTURE_NOTIFY; - xcb_change_window_attributes (conn, wnd->handle.xid, - XCB_CW_EVENT_MASK, &value); - } - /* Find the selected screen */ const xcb_setup_t *setup = xcb_get_setup (conn); - xcb_screen_t *screen = NULL; + const xcb_screen_t *screen = NULL; for (xcb_screen_iterator_t i = xcb_setup_roots_iterator (setup); i.rem > 0 && screen == NULL; xcb_screen_next (&i)) { @@ -110,12 +85,82 @@ vout_window_t *GetWindow (vout_thread_t *obj, if (screen == NULL) { msg_Err (obj, "parent window screen not found"); - goto error; + return NULL; } msg_Dbg (obj, "using screen 0x%"PRIx32, root); + return screen; +} + +static const xcb_screen_t *FindWindow (vlc_object_t *obj, + xcb_connection_t *conn, + xcb_window_t xid, + uint8_t *restrict pdepth) +{ + xcb_get_geometry_reply_t *geo = + xcb_get_geometry_reply (conn, xcb_get_geometry (conn, xid), NULL); + if (geo == NULL) + { + msg_Err (obj, "parent window not valid"); + return NULL; + } + + const xcb_screen_t *screen = FindScreen (obj, conn, geo->root); + *pdepth = geo->depth; + free (geo); + return screen; +} + + +/** + * Create a VLC video X window object, connect to the corresponding X server, + * find the corresponding X server screen. + */ +vout_window_t *GetWindow (vout_display_t *vd, + xcb_connection_t **restrict pconn, + const xcb_screen_t **restrict pscreen, + uint8_t *restrict pdepth) +{ + /* Get window */ + vout_window_cfg_t wnd_cfg; - /* Check MIT-SHM shared memory support */ - bool shm = var_CreateGetBool (obj, "x11-shm") > 0; + memset( &wnd_cfg, 0, sizeof(wnd_cfg) ); + wnd_cfg.type = VOUT_WINDOW_TYPE_XID; + wnd_cfg.x = var_InheritInteger (vd, "video-x"); + wnd_cfg.y = var_InheritInteger (vd, "video-y"); + 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 (vd, "parent window not available"); + return NULL; + } + + xcb_connection_t *conn = Connect (VLC_OBJECT(vd), wnd->display.x11); + if (conn == NULL) + goto error; + *pconn = conn; + + *pscreen = FindWindow (VLC_OBJECT(vd), conn, wnd->handle.xid, pdepth); + if (*pscreen == NULL) + { + xcb_disconnect (conn); + goto error; + } + + RegisterMouseEvents (VLC_OBJECT(vd), conn, wnd->handle.xid); + return wnd; + +error: + vout_display_DeleteWindow (vd, wnd); + return NULL; +} + +/** Check MIT-SHM shared memory support */ +void CheckSHM (vlc_object_t *obj, xcb_connection_t *conn, bool *restrict pshm) +{ + bool shm = var_InheritBool (obj, "x11-shm") > 0; if (shm) { xcb_shm_query_version_cookie_t ck; @@ -131,49 +176,27 @@ vout_window_t *GetWindow (vout_thread_t *obj, } free (r); } - - *pscreen = screen; *pshm = shm; - return wnd; - -error: - vout_ReleaseWindow (wnd); - return NULL; -} - -/** - * Gets the size of an X window. - */ -int GetWindowSize (struct vout_window_t *wnd, xcb_connection_t *conn, - unsigned *restrict width, unsigned *restrict height) -{ - xcb_get_geometry_cookie_t ck = xcb_get_geometry (conn, wnd->handle.xid); - xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply (conn, ck, NULL); - - if (!geo) - return -1; - - *width = geo->width; - *height = geo->height; - free (geo); - return 0; } /** * 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; } @@ -181,13 +204,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; @@ -195,9 +219,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; } } @@ -205,24 +229,20 @@ 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); + if (conn != NULL && segment != 0) xcb_shm_detach (conn, segment); - } - shmdt (pic->p->p_pixels); + shmdt (res->p->p_pixels); } +