]> git.sesse.net Git - vlc/blob - modules/video_output/xcb/pictures.c
xcb/glx: reuse the GLX provider code and eliminate a lot of code
[vlc] / modules / video_output / xcb / pictures.c
1 /**
2  * @file pictures.c
3  * @brief Pictures management code for XCB video output plugins
4  */
5 /*****************************************************************************
6  * Copyright © 2009-2013 Rémi Denis-Courmont
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 2.1 of the License, or
11  * (at your option) any later version.
12  *
13  * This program 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 Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
26
27 #include <stdlib.h>
28 #include <assert.h>
29 #include <errno.h>
30
31 #include <sys/types.h>
32 #ifdef HAVE_SYS_SHM_H
33 # include <sys/shm.h>
34 # include <sys/stat.h>
35 #else
36 # define shmdt(mem) free(mem)
37 #endif
38
39 #include <xcb/xcb.h>
40 #include <xcb/shm.h>
41
42 #include <vlc_common.h>
43 #include <vlc_vout_display.h>
44
45 #include "pictures.h"
46 #include "events.h"
47
48 /** Check MIT-SHM shared memory support */
49 bool XCB_shm_Check (vlc_object_t *obj, xcb_connection_t *conn)
50 {
51 #ifdef HAVE_SYS_SHM_H
52     xcb_shm_query_version_cookie_t ck;
53     xcb_shm_query_version_reply_t *r;
54
55     ck = xcb_shm_query_version (conn);
56     r = xcb_shm_query_version_reply (conn, ck, NULL);
57     if (r != NULL)
58     {
59         free (r);
60         return true;
61     }
62     msg_Err (obj, "shared memory (MIT-SHM) not available");
63     msg_Warn (obj, "display will be slow");
64 #else
65     msg_Warn (obj, "shared memory (MIT-SHM) not implemented");
66     (void) conn;
67 #endif
68     return false;
69 }
70
71 /**
72  * Release picture private data: detach the shared memory segment.
73  */
74 static void XCB_picture_Destroy (picture_t *pic)
75 {
76     shmdt (pic->p[0].p_pixels);
77     free (pic);
78 }
79
80 /**
81  * Initialize a picture buffer as shared memory, according to the video output
82  * format. If a attach is true, the segment is attached to
83  * the X server (MIT-SHM extension).
84  */
85 int XCB_picture_Alloc (vout_display_t *vd, picture_resource_t *res,
86                        size_t size, xcb_connection_t *conn,
87                        xcb_shm_seg_t segment)
88 {
89 #ifdef HAVE_SYS_SHM_H
90     /* Allocate shared memory segment */
91     int id = shmget (IPC_PRIVATE, size, IPC_CREAT | S_IRWXU);
92     if (id == -1)
93     {
94         msg_Err (vd, "shared memory allocation error: %s",
95                  vlc_strerror_c(errno));
96         return -1;
97     }
98
99     /* Attach the segment to VLC */
100     void *shm = shmat (id, NULL, 0 /* read/write */);
101     if (-1 == (intptr_t)shm)
102     {
103         msg_Err (vd, "shared memory attachment error: %s",
104                  vlc_strerror_c(errno));
105         shmctl (id, IPC_RMID, 0);
106         return -1;
107     }
108
109     if (segment != 0)
110     {   /* Attach the segment to X */
111         xcb_void_cookie_t ck = xcb_shm_attach_checked (conn, segment, id, 1);
112         switch (XCB_error_Check (vd, conn, "shared memory server-side error",
113                                  ck))
114         {
115             case 0:
116                 break;
117
118             case XCB_ACCESS:
119             {
120                 struct shmid_ds buf;
121                 /* Retry with promiscuous permissions */
122                 shmctl (id, IPC_STAT, &buf);
123                 buf.shm_perm.mode |= S_IRGRP|S_IROTH;
124                 shmctl (id, IPC_SET, &buf);
125                 ck = xcb_shm_attach_checked (conn, segment, id, 1);
126                 if (XCB_error_Check (vd, conn, "same error on retry", ck) == 0)
127                     break;
128                 /* fall through */
129             }
130
131             default:
132                 msg_Info (vd, "using buggy X11 server - SSH proxying?");
133                 segment = 0;
134         }
135     }
136
137     shmctl (id, IPC_RMID, NULL);
138 #else
139     assert (segment == 0);
140
141     /* XXX: align on 32 bytes for VLC chroma filters */
142     void *shm = malloc (size);
143     if (unlikely(shm == NULL))
144         return -1;
145 #endif
146     res->p_sys = (void *)(uintptr_t)segment;
147     res->pf_destroy = XCB_picture_Destroy;
148     res->p[0].p_pixels = shm;
149     return 0;
150 }
151
152 picture_t *XCB_picture_NewFromResource (const video_format_t *restrict fmt,
153                                         const picture_resource_t *restrict res)
154 {
155     picture_t *pic = picture_NewFromResource (fmt, res);
156     if (unlikely(pic == NULL))
157         shmdt (res->p[0].p_pixels);
158     return pic;
159 }