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 # 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)
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)
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)
84 struct vout_display_sys_t
86 vout_display_opengl_t *vgl;
88 vout_window_t *window;
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);
99 static vout_window_t *MakeWindow (vout_display_t *vd)
101 vout_window_cfg_t wnd_cfg;
103 memset (&wnd_cfg, 0, sizeof (wnd_cfg));
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;
121 # error Platform not recognized.
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;
128 vout_window_t *wnd = vout_display_NewWindow (vd, &wnd_cfg);
130 msg_Err (vd, "parent window not available");
135 * Allocates a surface and an OpenGL context for video output.
137 static int Open (vlc_object_t *obj)
139 vout_display_t *vd = (vout_display_t *)obj;
140 vout_display_sys_t *sys = malloc (sizeof (*sys));
141 if (unlikely(sys == NULL))
147 sys->window = MakeWindow (vd);
148 if (sys->window == NULL)
151 sys->gl = vlc_gl_Create (sys->window, API, "$" MODULE_VARNAME);
155 if (vlc_gl_MakeCurrent (sys->gl))
158 /* Initialize video display */
159 const vlc_fourcc_t *spu_chromas;
160 sys->vgl = vout_display_opengl_New (&vd->fmt, &spu_chromas, sys->gl);
165 vd->info.has_pictures_invalid = false;
166 vd->info.has_event_thread = false;
167 vd->info.subpicture_chromas = spu_chromas;
169 vd->prepare = PictureRender;
170 vd->display = PictureDisplay;
171 vd->control = Control;
177 vlc_gl_Destroy (sys->gl);
178 if (sys->window != NULL)
179 vout_display_DeleteWindow (vd, sys->window);
185 * Destroys the OpenGL context.
187 static void Close (vlc_object_t *obj)
189 vout_display_t *vd = (vout_display_t *)obj;
190 vout_display_sys_t *sys = vd->sys;
192 vout_display_opengl_Delete (sys->vgl);
193 vlc_gl_Destroy (sys->gl);
194 vout_display_DeleteWindow (vd, sys->window);
199 * Returns picture buffers
201 static picture_pool_t *Pool (vout_display_t *vd, unsigned count)
203 vout_display_sys_t *sys = vd->sys;
206 sys->pool = vout_display_opengl_GetPool (sys->vgl, count);
210 static void PictureRender (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
212 vout_display_sys_t *sys = vd->sys;
214 vout_display_opengl_Prepare (sys->vgl, pic, subpicture);
217 static void PictureDisplay (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
219 vout_display_sys_t *sys = vd->sys;
221 vout_display_opengl_Display (sys->vgl, &vd->source);
222 picture_Release (pic);
226 static int Control (vout_display_t *vd, int query, va_list ap)
228 vout_display_sys_t *sys = vd->sys;
232 case VOUT_DISPLAY_HIDE_MOUSE: /* FIXME TODO */
235 case VOUT_DISPLAY_RESET_PICTURES: // not needed
238 case VOUT_DISPLAY_CHANGE_FULLSCREEN:
240 const vout_display_cfg_t *cfg =
241 va_arg (ap, const vout_display_cfg_t *);
243 return vout_window_SetFullScreen (sys->window, cfg->is_fullscreen);
246 case VOUT_DISPLAY_CHANGE_WINDOW_STATE:
248 unsigned state = va_arg (ap, unsigned);
250 return vout_window_SetState (sys->window, state);
253 case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
254 case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
255 case VOUT_DISPLAY_CHANGE_ZOOM:
257 const vout_display_cfg_t *cfg = va_arg (ap, const vout_display_cfg_t *);
258 const video_format_t *src = &vd->source;
260 if (query == VOUT_DISPLAY_CHANGE_DISPLAY_SIZE)
264 force = va_arg (ap, int);
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))
273 vout_display_place_t place;
275 vout_display_PlacePicture (&place, src, cfg, false);
276 glViewport (0, 0, place.width, place.height);
280 case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
281 case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
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;
287 vout_display_PlacePicture (&place, src, cfg, false);
288 glViewport (0, 0, place.width, place.height);
292 case VOUT_DISPLAY_GET_OPENGL:
294 vlc_gl_t **pgl = va_arg (ap, vlc_gl_t **);
301 msg_Err (vd, "Unknown request %d", query);