3 * @brief OpenGL video output module
5 /*****************************************************************************
6 * Copyright © 2010-2011 Rémi Denis-Courmont
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.
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.
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 *****************************************************************************/
30 #include <vlc_common.h>
31 #include <vlc_plugin.h>
32 #include <vlc_vout_display.h>
33 #include <vlc_opengl.h>
36 /* Plugin callbacks */
37 static int Open (vlc_object_t *);
38 static void Close (vlc_object_t *);
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).")
47 #if USE_OPENGL_ES == 2
48 # define API VLC_OPENGL_ES2
49 # define MODULE_VARNAME "gles2"
50 set_shortname (N_("OpenGL ES2"))
51 set_description (N_("OpenGL for Embedded Systems 2 video output"))
52 set_capability ("vout display", /*165*/0)
53 set_callbacks (Open, Close)
54 add_shortcut ("opengles2", "gles2")
55 add_module ("gles2", "opengl es2", NULL,
56 GLES2_TEXT, PROVIDER_LONGTEXT, true)
58 #elif USE_OPENGL_ES == 1
59 # define API VLC_OPENGL_ES
60 # define MODULE_VARNAME "gles"
61 set_shortname (N_("OpenGL ES"))
62 set_description (N_("OpenGL for Embedded Systems video output"))
63 set_capability ("vout display", /*160*/0)
64 set_callbacks (Open, Close)
65 add_shortcut ("opengles", "gles")
66 add_module ("gles", "opengl es", NULL,
67 GLES_TEXT, PROVIDER_LONGTEXT, true)
69 # define API VLC_OPENGL
70 # define MODULE_VARNAME "gl"
71 set_shortname (N_("OpenGL"))
72 set_description (N_("OpenGL video output (experimental)"))
73 set_category (CAT_VIDEO)
74 set_subcategory (SUBCAT_VIDEO_VOUT)
75 set_capability ("vout display", /*170*/0)
76 set_callbacks (Open, Close)
77 add_shortcut ("opengl", "gl")
78 add_module ("gl", "opengl", NULL,
79 GL_TEXT, PROVIDER_LONGTEXT, true)
83 struct vout_display_sys_t
85 vout_display_opengl_t *vgl;
90 /* Display callbacks */
91 static picture_pool_t *Pool (vout_display_t *, unsigned);
92 static void PictureRender (vout_display_t *, picture_t *, subpicture_t *);
93 static void PictureDisplay (vout_display_t *, picture_t *, subpicture_t *);
94 static int Control (vout_display_t *, int, va_list);
96 static vout_window_t *MakeWindow (vout_display_t *vd)
98 vout_window_cfg_t cfg = {
99 .x = var_InheritInteger (vd, "video-x"),
100 .y = var_InheritInteger (vd, "video-y"),
101 .width = vd->cfg->display.width,
102 .height = vd->cfg->display.height,
107 cfg.type = VOUT_WINDOW_TYPE_HWND;
108 #elif defined(__ANDROID__)
109 cfg.type = VOUT_WINDOW_TYPE_ANDROID_NATIVE;
111 cfg.type = VOUT_WINDOW_TYPE_XID;
114 wnd = vout_display_NewWindow (vd, &cfg);
118 msg_Err (vd, "parent window not available");
123 * Allocates a surface and an OpenGL context for video output.
125 static int Open (vlc_object_t *obj)
127 vout_display_t *vd = (vout_display_t *)obj;
128 vout_display_sys_t *sys = malloc (sizeof (*sys));
129 if (unlikely(sys == NULL))
135 vout_window_t *surface = MakeWindow (vd);
139 sys->gl = vlc_gl_Create (surface, API, "$" MODULE_VARNAME);
143 /* Initialize video display */
144 const vlc_fourcc_t *spu_chromas;
146 if (vlc_gl_MakeCurrent (sys->gl))
149 sys->vgl = vout_display_opengl_New (&vd->fmt, &spu_chromas, sys->gl);
150 vlc_gl_ReleaseCurrent (sys->gl);
152 if (sys->vgl == NULL)
155 bool fs = vd->cfg->is_fullscreen;
156 if (vout_window_SetFullScreen (sys->gl->surface, fs))
158 vout_display_SendEventFullscreen (vd, fs);
161 vd->info.has_pictures_invalid = false;
162 vd->info.has_event_thread = false;
163 vd->info.subpicture_chromas = spu_chromas;
165 vd->prepare = PictureRender;
166 vd->display = PictureDisplay;
167 vd->control = Control;
173 vlc_gl_Destroy (sys->gl);
175 vout_display_DeleteWindow (vd, surface);
181 * Destroys the OpenGL context.
183 static void Close (vlc_object_t *obj)
185 vout_display_t *vd = (vout_display_t *)obj;
186 vout_display_sys_t *sys = vd->sys;
187 vlc_gl_t *gl = sys->gl;
188 vout_window_t *surface = gl->surface;
190 vlc_gl_MakeCurrent (gl);
191 vout_display_opengl_Delete (sys->vgl);
192 vlc_gl_ReleaseCurrent (gl);
195 vout_display_DeleteWindow (vd, surface);
200 * Returns picture buffers
202 static picture_pool_t *Pool (vout_display_t *vd, unsigned count)
204 vout_display_sys_t *sys = vd->sys;
208 vlc_gl_MakeCurrent (sys->gl);
209 sys->pool = vout_display_opengl_GetPool (sys->vgl, count);
210 vlc_gl_ReleaseCurrent (sys->gl);
215 static void PictureRender (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
217 vout_display_sys_t *sys = vd->sys;
219 vlc_gl_MakeCurrent (sys->gl);
220 vout_display_opengl_Prepare (sys->vgl, pic, subpicture);
221 vlc_gl_ReleaseCurrent (sys->gl);
224 static void PictureDisplay (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
226 vout_display_sys_t *sys = vd->sys;
228 vlc_gl_MakeCurrent (sys->gl);
229 vout_display_opengl_Display (sys->vgl, &vd->source);
230 vlc_gl_ReleaseCurrent (sys->gl);
232 picture_Release (pic);
236 static int Control (vout_display_t *vd, int query, va_list ap)
238 vout_display_sys_t *sys = vd->sys;
242 case VOUT_DISPLAY_HIDE_MOUSE: /* FIXME TODO */
245 case VOUT_DISPLAY_RESET_PICTURES: // not needed
248 case VOUT_DISPLAY_CHANGE_FULLSCREEN:
250 const vout_display_cfg_t *c =
251 va_arg (ap, const vout_display_cfg_t *);
253 return vout_window_SetFullScreen (sys->gl->surface, c->is_fullscreen);
256 case VOUT_DISPLAY_CHANGE_WINDOW_STATE:
258 unsigned state = va_arg (ap, unsigned);
260 return vout_window_SetState (sys->gl->surface, state);
263 case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
264 case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
265 case VOUT_DISPLAY_CHANGE_ZOOM:
267 const vout_display_cfg_t *c = va_arg (ap, const vout_display_cfg_t *);
268 const video_format_t *src = &vd->source;
270 if (query == VOUT_DISPLAY_CHANGE_DISPLAY_SIZE && va_arg (ap, int))
272 vout_window_SetSize (sys->gl->surface,
273 c->display.width, c->display.height);
277 vout_display_place_t place;
279 vout_display_PlacePicture (&place, src, c, false);
280 vlc_gl_MakeCurrent (sys->gl);
281 glViewport (place.x, place.y, place.width, place.height);
282 vlc_gl_ReleaseCurrent (sys->gl);
286 case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
287 case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
289 const vout_display_cfg_t *cfg = vd->cfg;
290 const video_format_t *src = va_arg (ap, const video_format_t *);
291 vout_display_place_t place;
293 vout_display_PlacePicture (&place, src, cfg, false);
294 vlc_gl_MakeCurrent (sys->gl);
295 glViewport (place.x, place.y, place.width, place.height);
296 vlc_gl_ReleaseCurrent (sys->gl);
300 case VOUT_DISPLAY_GET_OPENGL:
302 vlc_gl_t **pgl = va_arg (ap, vlc_gl_t **);
309 msg_Err (vd, "Unknown request %d", query);