3 * @brief EGL OpenGL extension 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 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_opengl.h>
34 #include <vlc_vout_window.h>
36 # include <vlc_xlib.h>
39 /* Plugin callbacks */
40 static int OpenGLES2 (vlc_object_t *);
41 static int OpenGLES (vlc_object_t *);
42 static int OpenGL (vlc_object_t *);
43 static void Close (vlc_object_t *);
46 set_shortname (N_("EGL"))
47 set_description (N_("EGL extension for OpenGL"))
48 set_category (CAT_VIDEO)
49 set_subcategory (SUBCAT_VIDEO_VOUT)
50 set_capability ("opengl", 50)
51 set_callbacks (OpenGL, Close)
54 set_capability ("opengl es2", 50)
55 set_callbacks (OpenGLES2, Close)
58 set_capability ("opengl es", 50)
59 set_callbacks (OpenGLES, Close)
63 typedef struct vlc_gl_sys_t
70 /* OpenGL callbacks */
71 static int MakeCurrent (vlc_gl_t *);
72 static void ReleaseCurrent (vlc_gl_t *);
73 static void SwapBuffers (vlc_gl_t *);
74 static void *GetSymbol(vlc_gl_t *, const char *);
76 static bool CheckAPI (EGLDisplay dpy, const char *api)
78 const char *apis = eglQueryString (dpy, EGL_CLIENT_APIS);
79 size_t apilen = strlen (api);
81 /* Cannot use strtok_r() on constant string... */
86 if (!strncmp (apis, api, apilen)
87 && (memchr (" ", apis[apilen], 2) != NULL))
90 apis = strchr (apis, ' ');
107 * Probe EGL display availability
109 static int Open (vlc_object_t *obj, const struct gl_api *api)
111 vlc_gl_t *gl = (vlc_gl_t *)obj;
113 /* <EGL/eglplatform.h> defines the list and order of platforms */
114 #if defined(_WIN32) || defined(__VC32__) \
115 && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
116 # define vlc_eglGetWindow(w) ((w)->handle.hwnd)
118 #elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
119 # error Symbian EGL not supported.
121 #elif defined(WL_EGL_PLATFORM)
122 # error Wayland EGL not supported.
124 #elif defined(__GBM__)
125 # error Glamor EGL not supported.
127 #elif defined(ANDROID)
128 # error Android EGL not supported
130 #elif defined(__unix__) /* X11 */
131 # define vlc_eglGetWindow(w) ((w)->handle.xid)
132 /* EGL can only use the default X11 display */
133 if (gl->surface->display.x11 != NULL)
135 if (!vlc_xlib_init (obj))
139 # error EGL platform not recognized.
142 /* Initialize EGL display */
143 /* TODO: support various display types */
144 EGLDisplay dpy = eglGetDisplay (EGL_DEFAULT_DISPLAY);
145 if (dpy == EGL_NO_DISPLAY)
148 vlc_gl_sys_t *sys = malloc (sizeof (*sys));
149 if (unlikely(sys == NULL))
155 if (eglInitialize (dpy, &major, &minor) != EGL_TRUE)
157 /* No need to call eglTerminate() in this case */
162 if (major != 1 || minor < api->min_minor || !CheckAPI (dpy, api->name))
165 msg_Dbg (obj, "EGL version %s by %s", eglQueryString (dpy, EGL_VERSION),
166 eglQueryString (dpy, EGL_VENDOR));
168 const char *ext = eglQueryString (dpy, EGL_EXTENSIONS);
170 msg_Dbg (obj, " extensions: %s", ext);
173 const EGLint conf_attr[] = {
177 EGL_RENDERABLE_TYPE, api->render_bit,
183 if (eglChooseConfig (dpy, conf_attr, cfgv, 1, &cfgc) != EGL_TRUE
186 msg_Err (obj, "cannot choose EGL configuration");
190 /* Create a drawing surface */
191 EGLNativeWindowType win = vlc_eglGetWindow(gl->surface);
192 EGLSurface surface = eglCreateWindowSurface (dpy, cfgv[0], win, NULL);
193 if (surface == EGL_NO_SURFACE)
195 msg_Err (obj, "cannot create EGL window surface");
198 sys->surface = surface;
200 if (eglBindAPI (api->api) != EGL_TRUE)
202 msg_Err (obj, "cannot bind EGL API");
206 EGLContext ctx = eglCreateContext (dpy, cfgv[0], EGL_NO_CONTEXT,
208 if (ctx == EGL_NO_CONTEXT)
210 msg_Err (obj, "cannot create EGL context");
215 /* Initialize OpenGL callbacks */
217 gl->makeCurrent = MakeCurrent;
218 gl->releaseCurrent = ReleaseCurrent;
219 gl->swap = SwapBuffers;
220 gl->getProcAddress = GetSymbol;
230 static int OpenGLES2 (vlc_object_t *obj)
232 static const struct gl_api api = {
233 "OpenGL_ES", EGL_OPENGL_ES_API, 3, EGL_OPENGL_ES2_BIT,
234 { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE },
236 return Open (obj, &api);
239 static int OpenGLES (vlc_object_t *obj)
241 static const struct gl_api api = {
242 "OpenGL_ES", EGL_OPENGL_ES_API, 0, EGL_OPENGL_ES_BIT,
243 { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE },
245 return Open (obj, &api);
248 static int OpenGL (vlc_object_t *obj)
250 static const struct gl_api api = {
251 "OpenGL", EGL_OPENGL_API, 4, EGL_OPENGL_BIT,
254 return Open (obj, &api);
257 static void Close (vlc_object_t *obj)
259 vlc_gl_t *gl = (vlc_gl_t *)obj;
260 vlc_gl_sys_t *sys = gl->sys;
262 eglTerminate (sys->display);
266 static int MakeCurrent (vlc_gl_t *gl)
268 vlc_gl_sys_t *sys = gl->sys;
270 if (eglMakeCurrent (sys->display, sys->surface, sys->surface,
271 sys->context) != EGL_TRUE)
276 static void ReleaseCurrent (vlc_gl_t *gl)
278 vlc_gl_sys_t *sys = gl->sys;
280 eglMakeCurrent (sys->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
284 static void SwapBuffers (vlc_gl_t *gl)
286 vlc_gl_sys_t *sys = gl->sys;
288 eglSwapBuffers (sys->display, sys->surface);
291 static void *GetSymbol(vlc_gl_t *gl, const char *procname)
294 return (void *)eglGetProcAddress (procname);