vout: remove no longer used VOUT_DISPLAY_GET_OPENGL
[vlc.git] / modules / video_output / xcb / glx.c
1 /**
2  * @file glx.c
3  * @brief GLX video output module for VLC media player
4  */
5 /*****************************************************************************
6  * Copyright © 2004 VLC authors and VideoLAN
7  * Copyright © 2009 Rémi Denis-Courmont
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27
28 #include <stdlib.h>
29 #include <assert.h>
30
31 #include <xcb/xcb.h>
32
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_vout_display.h>
36 #include <vlc_opengl.h>
37 #include "../opengl.h"
38
39 #include "events.h"
40
41 static int  Open (vlc_object_t *);
42 static void Close (vlc_object_t *);
43
44 /*
45  * Module descriptor
46  */
47 vlc_module_begin ()
48     set_shortname (N_("GLX"))
49     set_description (N_("OpenGL GLX video output (XCB)"))
50     set_category (CAT_VIDEO)
51     set_subcategory (SUBCAT_VIDEO_VOUT)
52     set_capability ("vout display", 150)
53     set_callbacks (Open, Close)
54
55     add_shortcut ("xcb-glx", "glx", "opengl", "xid")
56 vlc_module_end ()
57
58 struct vout_display_sys_t
59 {
60     xcb_connection_t *conn; /**< XCB connection */
61     vlc_gl_t *gl;
62
63     xcb_cursor_t cursor; /* blank cursor */
64     bool visible; /* whether to draw */
65
66     vout_display_opengl_t *vgl;
67     picture_pool_t *pool; /* picture pool */
68 };
69
70 static picture_pool_t *Pool (vout_display_t *, unsigned);
71 static void PictureRender (vout_display_t *, picture_t *, subpicture_t *);
72 static void PictureDisplay (vout_display_t *, picture_t *, subpicture_t *);
73 static int Control (vout_display_t *, int, va_list);
74 static void Manage (vout_display_t *);
75
76 /**
77  * Probe the X server.
78  */
79 static int Open (vlc_object_t *obj)
80 {
81     vout_display_t *vd = (vout_display_t *)obj;
82     vout_display_sys_t *sys = malloc (sizeof (*sys));
83
84     if (sys == NULL)
85         return VLC_ENOMEM;
86
87     sys->vgl = NULL;
88     sys->pool = NULL;
89
90     /* Get window, connect to X server (via XCB) */
91     xcb_connection_t *conn;
92     const xcb_screen_t *scr;
93     vout_window_t *surface;
94
95     surface = XCB_parent_Create (vd, &conn, &scr);
96     if (surface == NULL)
97     {
98         free (sys);
99         return VLC_EGENERIC;
100     }
101
102     sys->conn = conn;
103     sys->gl = vlc_gl_Create (surface, VLC_OPENGL, "glx");
104     if (sys->gl == NULL)
105         goto error;
106
107     const vlc_fourcc_t *spu_chromas;
108
109     if (vlc_gl_MakeCurrent (sys->gl))
110         goto error;
111
112     sys->vgl = vout_display_opengl_New (&vd->fmt, &spu_chromas, sys->gl);
113     vlc_gl_ReleaseCurrent (sys->gl);
114     if (sys->vgl == NULL)
115         goto error;
116
117     sys->cursor = XCB_cursor_Create (conn, scr);
118     sys->visible = false;
119
120     /* Setup vout_display_t once everything is fine */
121     vd->sys = sys;
122     vd->info.has_pictures_invalid = false;
123     vd->info.has_event_thread = true;
124     vd->info.subpicture_chromas = spu_chromas;
125     vd->pool = Pool;
126     vd->prepare = PictureRender;
127     vd->display = PictureDisplay;
128     vd->control = Control;
129     vd->manage = Manage;
130
131     return VLC_SUCCESS;
132
133 error:
134     if (sys->gl != NULL)
135         vlc_gl_Destroy (sys->gl);
136     xcb_disconnect (sys->conn);
137     vout_display_DeleteWindow (vd, surface);
138     free (sys);
139     return VLC_EGENERIC;
140 }
141
142
143 /**
144  * Disconnect from the X server.
145  */
146 static void Close (vlc_object_t *obj)
147 {
148     vout_display_t *vd = (vout_display_t *)obj;
149     vout_display_sys_t *sys = vd->sys;
150     vlc_gl_t *gl = sys->gl;
151     vout_window_t *surface = gl->surface;
152
153     vlc_gl_MakeCurrent (gl);
154     vout_display_opengl_Delete (sys->vgl);
155     vlc_gl_ReleaseCurrent (gl);
156     vlc_gl_Destroy (gl);
157
158     /* show the default cursor */
159     xcb_change_window_attributes (sys->conn, surface->handle.xid,
160                                XCB_CW_CURSOR, &(uint32_t) { XCB_CURSOR_NONE });
161     xcb_flush (sys->conn);
162     xcb_disconnect (sys->conn);
163
164     vout_display_DeleteWindow (vd, surface);
165     free (sys);
166 }
167
168 /**
169  * Return a direct buffer
170  */
171 static picture_pool_t *Pool (vout_display_t *vd, unsigned requested_count)
172 {
173     vout_display_sys_t *sys = vd->sys;
174
175     if (!sys->pool)
176     {
177         vlc_gl_MakeCurrent (sys->gl);
178         sys->pool = vout_display_opengl_GetPool (sys->vgl, requested_count);
179         vlc_gl_ReleaseCurrent (sys->gl);
180     }
181     return sys->pool;
182 }
183
184 static void PictureRender (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
185 {
186     vout_display_sys_t *sys = vd->sys;
187
188     vlc_gl_MakeCurrent (sys->gl);
189     vout_display_opengl_Prepare (sys->vgl, pic, subpicture);
190     vlc_gl_ReleaseCurrent (sys->gl);
191 }
192
193 static void PictureDisplay (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
194 {
195     vout_display_sys_t *sys = vd->sys;
196
197     vlc_gl_MakeCurrent (sys->gl);
198     vout_display_opengl_Display (sys->vgl, &vd->source);
199     vlc_gl_ReleaseCurrent (sys->gl);
200
201     picture_Release (pic);
202     if (subpicture)
203         subpicture_Delete(subpicture);
204 }
205
206 static int Control (vout_display_t *vd, int query, va_list ap)
207 {
208     vout_display_sys_t *sys = vd->sys;
209
210     switch (query)
211     {
212     case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
213     case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
214     case VOUT_DISPLAY_CHANGE_ZOOM:
215     case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
216     case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
217     {
218         const vout_display_cfg_t *cfg;
219         const video_format_t *source;
220
221         if (query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT
222          || query == VOUT_DISPLAY_CHANGE_SOURCE_CROP)
223         {
224             source = (const video_format_t *)va_arg (ap, const video_format_t *);
225             cfg = vd->cfg;
226         }
227         else
228         {
229             source = &vd->source;
230             cfg = (const vout_display_cfg_t*)va_arg (ap, const vout_display_cfg_t *);
231         }
232
233         vout_display_place_t place;
234         vout_display_PlacePicture (&place, source, cfg, false);
235
236         vlc_gl_MakeCurrent (sys->gl);
237         glViewport (place.x, place.y, place.width, place.height);
238         vlc_gl_ReleaseCurrent (sys->gl);
239         return VLC_SUCCESS;
240     }
241
242     /* Hide the mouse. It will be send when
243      * vout_display_t::info.b_hide_mouse is false */
244     case VOUT_DISPLAY_HIDE_MOUSE:
245         xcb_change_window_attributes (sys->conn, sys->gl->surface->handle.xid,
246                                     XCB_CW_CURSOR, &(uint32_t){ sys->cursor });
247         xcb_flush (sys->conn);
248         return VLC_SUCCESS;
249
250     case VOUT_DISPLAY_RESET_PICTURES:
251         assert (0);
252     default:
253         msg_Err (vd, "Unknown request in XCB vout display");
254         return VLC_EGENERIC;
255     }
256 }
257
258 static void Manage (vout_display_t *vd)
259 {
260     vout_display_sys_t *sys = vd->sys;
261
262     XCB_Manage (vd, sys->conn, &sys->visible);
263 }