]> git.sesse.net Git - vlc/blob - modules/video_output/gl.c
Remove VOUT_WINDOW_TYPE_NATIVE (close #7666)
[vlc] / modules / video_output / gl.c
1 /**
2  * @file gl.c
3  * @brief OpenGL video output module
4  */
5 /*****************************************************************************
6  * Copyright © 2010-2011 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
30 #include <vlc_common.h>
31 #include <vlc_plugin.h>
32 #include <vlc_vout_display.h>
33 #include <vlc_opengl.h>
34 #include "opengl.h"
35
36 /* Plugin callbacks */
37 static int Open (vlc_object_t *);
38 static void Close (vlc_object_t *);
39
40 #define GL_TEXT N_("OpenGL extension")
41 #define GLES2_TEXT N_("OpenGL ES 2 extension")
42 #define GLES_TEXT N_("OpenGL ES extension")
43 #define PROVIDER_LONGTEXT N_( \
44     "Extension through which to use the Open Graphics Library (OpenGL).")
45
46 vlc_module_begin ()
47 #if USE_OPENGL_ES == 2
48 # error The OpenGL ES2 plugin is incomplete and not functional. FIXME.
49 # define API VLC_OPENGL_ES2
50 # define MODULE_VARNAME "gles2"
51     set_shortname (N_("OpenGL ES2"))
52     set_description (N_("OpenGL for Embedded Systems 2 video output"))
53     set_capability ("vout display", /*165*/0)
54     set_callbacks (Open, Close)
55     add_shortcut ("opengles2", "gles2")
56     add_module ("gles2", "opengl es2", NULL,
57                 GLES2_TEXT, PROVIDER_LONGTEXT, true)
58
59 #elif USE_OPENGL_ES == 1
60 # define API VLC_OPENGL_ES
61 # define MODULE_VARNAME "gles"
62     set_shortname (N_("OpenGL ES"))
63     set_description (N_("OpenGL for Embedded Systems video output"))
64     set_capability ("vout display", /*160*/0)
65     set_callbacks (Open, Close)
66     add_shortcut ("opengles", "gles")
67     add_module ("gles", "opengl es", NULL,
68                 GLES_TEXT, PROVIDER_LONGTEXT, true)
69 #else
70 # define API VLC_OPENGL
71 # define MODULE_VARNAME "gl"
72     set_shortname (N_("OpenGL"))
73     set_description (N_("OpenGL video output (experimental)"))
74     set_category (CAT_VIDEO)
75     set_subcategory (SUBCAT_VIDEO_VOUT)
76     set_capability ("vout display", /*170*/0)
77     set_callbacks (Open, Close)
78     add_shortcut ("opengl", "gl")
79     add_module ("gl", "opengl", NULL,
80                 GL_TEXT, PROVIDER_LONGTEXT, true)
81 #endif
82 vlc_module_end ()
83
84 struct vout_display_sys_t
85 {
86     vout_display_opengl_t *vgl;
87
88     vout_window_t *window;
89     vlc_gl_t *gl;
90     picture_pool_t *pool;
91 };
92
93 /* Display callbacks */
94 static picture_pool_t *Pool (vout_display_t *, unsigned);
95 static void PictureRender (vout_display_t *, picture_t *, subpicture_t *);
96 static void PictureDisplay (vout_display_t *, picture_t *, subpicture_t *);
97 static int Control (vout_display_t *, int, va_list);
98
99 static vout_window_t *MakeWindow (vout_display_t *vd)
100 {
101     vout_window_cfg_t wnd_cfg;
102
103     memset (&wnd_cfg, 0, sizeof (wnd_cfg));
104
105     /* Please keep this in sync with egl.c */
106     /* <EGL/eglplatform.h> defines the list and order of platforms */
107 #if defined(_WIN32) || defined(__VC32__) \
108  && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
109     wnd_cfg.type = VOUT_WINDOW_TYPE_HWND;
110 #elif defined(__WINSCW__) || defined(__SYMBIAN32__)  /* Symbian */
111 # warning Symbian not supported.
112 #elif defined(WL_EGL_PLATFORM)
113 # error Wayland not supported.
114 #elif defined(__GBM__)
115 # error Glamor not supported.
116 #elif defined(ANDROID)
117 # error Android not supported.
118 #elif defined(__unix__) /* X11 */
119     wnd_cfg.type = VOUT_WINDOW_TYPE_XID;
120 #else
121 # error Platform not recognized.
122 #endif
123     wnd_cfg.x = var_InheritInteger (vd, "video-x");
124     wnd_cfg.y = var_InheritInteger (vd, "video-y");
125     wnd_cfg.width  = vd->cfg->display.width;
126     wnd_cfg.height = vd->cfg->display.height;
127
128     vout_window_t *wnd = vout_display_NewWindow (vd, &wnd_cfg);
129     if (wnd == NULL)
130         msg_Err (vd, "parent window not available");
131     return wnd;
132 }
133
134 /**
135  * Allocates a surface and an OpenGL context for video output.
136  */
137 static int Open (vlc_object_t *obj)
138 {
139     vout_display_t *vd = (vout_display_t *)obj;
140     vout_display_sys_t *sys = malloc (sizeof (*sys));
141     if (unlikely(sys == NULL))
142         return VLC_ENOMEM;
143
144     sys->gl = NULL;
145     sys->pool = NULL;
146
147     sys->window = MakeWindow (vd);
148     if (sys->window == NULL)
149         goto error;
150
151     sys->gl = vlc_gl_Create (sys->window, API, "$" MODULE_VARNAME);
152     if (sys->gl == NULL)
153         goto error;
154
155     if (vlc_gl_MakeCurrent (sys->gl))
156         goto error;
157
158     /* Initialize video display */
159     const vlc_fourcc_t *spu_chromas;
160     sys->vgl = vout_display_opengl_New (&vd->fmt, &spu_chromas, sys->gl);
161     if (!sys->vgl)
162         goto error;
163
164     vd->sys = sys;
165     vd->info.has_pictures_invalid = false;
166     vd->info.has_event_thread = false;
167     vd->info.subpicture_chromas = spu_chromas;
168     vd->pool = Pool;
169     vd->prepare = PictureRender;
170     vd->display = PictureDisplay;
171     vd->control = Control;
172     vd->manage = NULL;
173     return VLC_SUCCESS;
174
175 error:
176     if (sys->gl != NULL)
177         vlc_gl_Destroy (sys->gl);
178     if (sys->window != NULL)
179         vout_display_DeleteWindow (vd, sys->window);
180     free (sys);
181     return VLC_EGENERIC;
182 }
183
184 /**
185  * Destroys the OpenGL context.
186  */
187 static void Close (vlc_object_t *obj)
188 {
189     vout_display_t *vd = (vout_display_t *)obj;
190     vout_display_sys_t *sys = vd->sys;
191
192     vout_display_opengl_Delete (sys->vgl);
193     vlc_gl_Destroy (sys->gl);
194     vout_display_DeleteWindow (vd, sys->window);
195     free (sys);
196 }
197
198 /**
199  * Returns picture buffers
200  */
201 static picture_pool_t *Pool (vout_display_t *vd, unsigned count)
202 {
203     vout_display_sys_t *sys = vd->sys;
204
205     if (!sys->pool)
206         sys->pool = vout_display_opengl_GetPool (sys->vgl, count);
207     return sys->pool;
208 }
209
210 static void PictureRender (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
211 {
212     vout_display_sys_t *sys = vd->sys;
213
214     vout_display_opengl_Prepare (sys->vgl, pic, subpicture);
215 }
216
217 static void PictureDisplay (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
218 {
219     vout_display_sys_t *sys = vd->sys;
220
221     vout_display_opengl_Display (sys->vgl, &vd->source);
222     picture_Release (pic);
223     (void)subpicture;
224 }
225
226 static int Control (vout_display_t *vd, int query, va_list ap)
227 {
228     vout_display_sys_t *sys = vd->sys;
229
230     switch (query)
231     {
232       case VOUT_DISPLAY_HIDE_MOUSE: /* FIXME TODO */
233         break;
234 #ifndef NDEBUG
235       case VOUT_DISPLAY_RESET_PICTURES: // not needed
236         assert(0);
237 #endif
238       case VOUT_DISPLAY_CHANGE_FULLSCREEN:
239       {
240         const vout_display_cfg_t *cfg =
241             va_arg (ap, const vout_display_cfg_t *);
242
243         return vout_window_SetFullScreen (sys->window, cfg->is_fullscreen);
244       }
245
246       case VOUT_DISPLAY_CHANGE_WINDOW_STATE:
247       {
248         unsigned state = va_arg (ap, unsigned);
249
250         return vout_window_SetState (sys->window, state);
251       }
252
253       case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
254       case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
255       case VOUT_DISPLAY_CHANGE_ZOOM:
256       {
257         const vout_display_cfg_t *cfg = va_arg (ap, const vout_display_cfg_t *);
258         const video_format_t *src = &vd->source;
259
260         if (query == VOUT_DISPLAY_CHANGE_DISPLAY_SIZE)
261         {
262             bool force = false;
263
264             force = va_arg (ap, int);
265             if (force
266              && (cfg->display.width  != vd->cfg->display.width
267               || cfg->display.height != vd->cfg->display.height)
268              && vout_window_SetSize (sys->window,
269                                      cfg->display.width, cfg->display.height))
270                 return VLC_EGENERIC;
271         }
272
273         vout_display_place_t place;
274
275         vout_display_PlacePicture (&place, src, cfg, false);
276         glViewport (0, 0, place.width, place.height);
277         return VLC_SUCCESS;
278       }
279
280       case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
281       case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
282       {
283         const vout_display_cfg_t *cfg = vd->cfg;
284         const video_format_t *src = va_arg (ap, const video_format_t *);
285         vout_display_place_t place;
286
287         vout_display_PlacePicture (&place, src, cfg, false);
288         glViewport (0, 0, place.width, place.height);
289         return VLC_SUCCESS;
290       }
291
292       case VOUT_DISPLAY_GET_OPENGL:
293       {
294         vlc_gl_t **pgl = va_arg (ap, vlc_gl_t **);
295
296         *pgl = sys->gl;
297         return VLC_SUCCESS;
298       }
299
300       default:
301         msg_Err (vd, "Unknown request %d", query);
302     }
303     return VLC_EGENERIC;
304 }