3 * @brief EGL OpenGL extension module
5 /*****************************************************************************
6 * Copyright © 2010-2011 Rémi Denis-Courmont
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1
11 * of the License, or (at your option) any later version.
13 * This library 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 General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, 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>
40 /* Plugin callbacks */
41 static int OpenGLES2 (vlc_object_t *);
42 static int OpenGLES (vlc_object_t *);
43 static int OpenGL (vlc_object_t *);
44 static void Close (vlc_object_t *);
47 set_shortname (N_("EGL"))
48 set_description (N_("EGL extension for OpenGL"))
49 set_category (CAT_VIDEO)
50 set_subcategory (SUBCAT_VIDEO_VOUT)
51 set_capability ("opengl", 50)
52 set_callbacks (OpenGL, Close)
55 set_capability ("opengl es2", 50)
56 set_callbacks (OpenGLES2, Close)
59 set_capability ("opengl es", 50)
60 set_callbacks (OpenGLES, Close)
64 typedef struct vlc_gl_sys_t
71 /* OpenGL callbacks */
72 static int MakeCurrent (vlc_gl_t *);
73 static void SwapBuffers (vlc_gl_t *);
75 static bool CheckAPI (EGLDisplay dpy, const char *api)
77 const char *apis = eglQueryString (dpy, EGL_CLIENT_APIS);
78 size_t apilen = strlen (api);
80 /* Cannot use strtok_r() on constant string... */
83 if (!strncmp (apis, api, apilen)
84 && (memchr (" ", apis[apilen], 2) != NULL))
87 apis = strchr (apis, ' ');
104 * Probe EGL display availability
106 static int Open (vlc_object_t *obj, const struct gl_api *api)
108 vlc_gl_t *gl = (vlc_gl_t *)obj;
111 /* EGL can only use the default X11 display */
112 if (gl->surface->display.x11 != NULL)
114 if (!vlc_xlib_init (obj))
118 /* Initialize EGL display */
119 /* TODO: support various display types */
120 EGLDisplay dpy = eglGetDisplay (EGL_DEFAULT_DISPLAY);
121 if (dpy == EGL_NO_DISPLAY)
124 vlc_gl_sys_t *sys = malloc (sizeof (*sys));
125 if (unlikely(sys == NULL))
131 /* XXX Explicit hack!
132 * Mesa EGL plugins (as of version 7.8.2) are not properly linked to
133 * libEGL.so even though they import some of its symbols. This is
134 * typically not a problem. Unfortunately, LibVLC loads plugins as
135 * RTLD_LOCAL so that they do not pollute the namespace. Then the
136 * libEGL symbols are not visible to EGL plugins, and the run-time
137 * linker exits the whole process. */
138 if (dlopen ("libEGL.so", RTLD_GLOBAL|RTLD_NOW) == NULL)
139 msg_Warn (gl, "libEGL cannot be loaded. Process might crash.");
140 if (dlopen ("libGL.so", RTLD_GLOBAL|RTLD_NOW) == NULL)
141 msg_Warn (gl, "libGL cannot be loaded. Process might crash.");
145 if (eglInitialize (dpy, &major, &minor) != EGL_TRUE)
147 /* No need to call eglTerminate() in this case */
152 if (major != 1 || minor < api->min_minor || !CheckAPI (dpy, api->name))
155 msg_Dbg (obj, "EGL version %s by %s", eglQueryString (dpy, EGL_VERSION),
156 eglQueryString (dpy, EGL_VENDOR));
158 const char *ext = eglQueryString (dpy, EGL_EXTENSIONS);
160 msg_Dbg (obj, " extensions: %s", ext);
163 const EGLint conf_attr[] = {
167 EGL_RENDERABLE_TYPE, api->render_bit,
173 if (eglChooseConfig (dpy, conf_attr, cfgv, 1, &cfgc) != EGL_TRUE
177 /* Create a drawing surface */
179 EGLNativeWindowType win = gl->surface->handle.hwnd;
180 #elif defined (__unix__)
181 EGLNativeWindowType win = gl->surface->handle.xid;
184 EGLSurface surface = eglCreateWindowSurface (dpy, cfgv[0], win, NULL);
185 if (surface == EGL_NO_SURFACE)
187 msg_Err (obj, "cannot create EGL window surface");
190 sys->surface = surface;
192 if (eglBindAPI (api->api) != EGL_TRUE)
194 msg_Err (obj, "cannot bind EGL API");
198 EGLContext ctx = eglCreateContext (dpy, cfgv[0], EGL_NO_CONTEXT,
200 if (ctx == EGL_NO_CONTEXT)
202 msg_Err (obj, "cannot create EGL context");
207 /* Initialize OpenGL callbacks */
209 gl->makeCurrent = MakeCurrent;
210 gl->swap = SwapBuffers;
220 static int OpenGLES2 (vlc_object_t *obj)
222 static const struct gl_api api = {
223 "OpenGL_ES", EGL_OPENGL_ES_API, 3, EGL_OPENGL_ES2_BIT,
224 { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE },
226 return Open (obj, &api);
229 static int OpenGLES (vlc_object_t *obj)
231 static const struct gl_api api = {
232 "OpenGL_ES", EGL_OPENGL_ES_API, 0, EGL_OPENGL_ES_BIT,
233 { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE },
235 return Open (obj, &api);
238 static int OpenGL (vlc_object_t *obj)
240 static const struct gl_api api = {
241 "OpenGL", EGL_OPENGL_API, 4, EGL_OPENGL_BIT,
244 return Open (obj, &api);
247 static void Close (vlc_object_t *obj)
249 vlc_gl_t *gl = (vlc_gl_t *)obj;
250 vlc_gl_sys_t *sys = gl->sys;
252 eglTerminate (sys->display);
256 static int MakeCurrent (vlc_gl_t *gl)
258 vlc_gl_sys_t *sys = gl->sys;
260 if (eglMakeCurrent (sys->display, sys->surface, sys->surface,
261 sys->context) != EGL_TRUE)
266 static void SwapBuffers (vlc_gl_t *gl)
268 vlc_gl_sys_t *sys = gl->sys;
270 eglSwapBuffers (sys->display, sys->surface);