# HG changeset patch # User reimar # Date 1323550531 0 # Node ID 4a507d3a039ae61425e8560f9a8293a21589a5d2 # Parent f8c523d09e5ee938edd3484c1a9f967b25f17564 Add highly experimental support for OpenGL ES. It only supports EGL/X11, uses/supports only ES v1, will crash if certain features are used, compiling without desktop GL installed is not tested and possibly more caveats. However it is close enough to be able to display a video on a BeagleBoard via OpenGL. Performance could not be tested properly since I do not have a display that is compatible with the BeagleBoard output... diff -r f8c523d09e5e -r 4a507d3a039a configure --- a/configure Sat Dec 10 20:21:50 2011 +0000 +++ b/configure Sat Dec 10 20:55:31 2011 +0000 @@ -5064,6 +5064,10 @@ // we allow SDL hacking our main() only on OSX #undef main #endif +#elif defined(GL_EGL_X11) +#include +#include +#include #else #include #include @@ -5075,10 +5079,15 @@ wglCreateContext(dc); #elif defined(GL_SDL) SDL_GL_SwapBuffers(); +#elif defined(GL_EGL_X11) + EGLDisplay eglDisplay = EGL_NO_DISPLAY; + eglInitialize(eglDisplay, NULL, NULL); #else glXCreateContext(NULL, NULL, NULL, True); #endif +#ifndef GL_EGL_X11 glFinish(); +#endif return 0; } EOF @@ -5091,6 +5100,11 @@ break fi done + if cc_check -DGL_EGL_X11 -lEGL ; then + _gl=yes + _gl_egl_x11=yes + libs_mplayer="$libs_mplayer -lEGL $ld_dl" + fi if cc_check -DGL_WIN32 -lopengl32 ; then _gl=yes _gl_win32=yes @@ -5123,6 +5137,10 @@ def_gl_x11='#define CONFIG_GL_X11 1' res_comment="$res_comment x11" fi + if test "$_gl_egl_x11" = yes ; then + def_gl_egl_x11='#define CONFIG_GL_EGL_X11 1' + res_comment="$res_comment egl_x11" + fi if test "$_gl_sdl" = yes ; then def_gl_sdl='#define CONFIG_GL_SDL 1' res_comment="$res_comment sdl" @@ -5132,6 +5150,7 @@ def_gl='#undef CONFIG_GL' def_gl_win32='#undef CONFIG_GL_WIN32' def_gl_x11='#undef CONFIG_GL_X11' + def_gl_egl_x11='#undef CONFIG_GL_EGL_X11' def_gl_sdl='#undef CONFIG_GL_SDL' novomodules="opengl $novomodules" fi @@ -8030,6 +8049,7 @@ GL = $_gl GL_WIN32 = $_gl_win32 GL_X11 = $_gl_x11 +GL_EGL_X11 = $_gl_egl_x11 GL_SDL = $_gl_sdl MATRIXVIEW = $matrixview GUI = $_gui @@ -8569,6 +8589,7 @@ $def_gl $def_gl_win32 $def_gl_x11 +$def_gl_egl_x11 $def_gl_sdl $def_matrixview $def_ivtv diff -r f8c523d09e5e -r 4a507d3a039a libvo/gl_common.c --- a/libvo/gl_common.c Sat Dec 10 20:21:50 2011 +0000 +++ b/libvo/gl_common.c Sat Dec 10 20:55:31 2011 +0000 @@ -139,6 +139,14 @@ void (GLAPIENTRY *mpglFreeMemoryMESA)(void *, int, void *); /** \} */ // end of glextfunctions group + +void (GLAPIENTRY *mpglVertexPointer)(GLint, GLenum, GLsizei, const GLvoid *); +void (GLAPIENTRY *mpglTexCoordPointer)(GLint, GLenum, GLsizei, const GLvoid *); +void (GLAPIENTRY *mpglClientActiveTexture)(GLenum); +void (GLAPIENTRY *mpglEnableClientState)(GLenum); +void (GLAPIENTRY *mpglDisableClientState)(GLenum); +void (GLAPIENTRY *mpglDrawArrays)(GLenum, GLint, GLsizei); + //! \defgroup glgeneral OpenGL general helper functions //! \defgroup glcontext OpenGL context management helper functions @@ -384,7 +392,11 @@ void *fallback; } extfunc_desc_t; +#if !defined(CONFIG_GL_WIN32) && !defined(CONFIG_GL_X11) +#define DEF_FUNC_DESC(name) {&mpgl##name, NULL, {"gl"#name, NULL}, NULL} +#else #define DEF_FUNC_DESC(name) {&mpgl##name, NULL, {"gl"#name, NULL}, gl ##name} +#endif static const extfunc_desc_t extfuncs[] = { // these aren't extension functions but we query them anyway to allow // different "backends" with one binary @@ -466,6 +478,14 @@ {&mpglTexImage3D, NULL, {"glTexImage3D", NULL}}, {&mpglAllocateMemoryMESA, "GLX_MESA_allocate_memory", {"glXAllocateMemoryMESA", NULL}}, {&mpglFreeMemoryMESA, "GLX_MESA_allocate_memory", {"glXFreeMemoryMESA", NULL}}, + + // Things needed to run on GLES + {&mpglVertexPointer, NULL, {"glVertexPointer", NULL}}, + {&mpglTexCoordPointer, NULL, {"glTexCoordPointer", NULL}}, + {&mpglClientActiveTexture, NULL, {"glClientActiveTexture", NULL}}, + {&mpglEnableClientState, NULL, {"glEnableClientState", NULL}}, + {&mpglDisableClientState, NULL, {"glDisableClientState", NULL}}, + {&mpglDrawArrays, NULL, {"glDrawArrays", NULL}}, {NULL} }; @@ -1685,6 +1705,36 @@ y += h; h = -h; } + + if (!mpglBegin) { + GLfloat vertices [8] = { x, y, x, y + h, x + w, y, x + w, y + h}; + GLfloat texcoords [8] = {tx, ty, tx, ty + th, tx + tw, ty, tx + tw, ty + th}; + GLfloat texcoords2[8] = {tx2, ty2, tx2, ty2 + th2, tx2 + tw2, ty2, tx2 + tw2, ty2 + th2}; + mpglEnableClientState(GL_VERTEX_ARRAY); + mpglVertexPointer(2, GL_FLOAT, 0, vertices); + mpglEnableClientState(GL_TEXTURE_COORD_ARRAY); + mpglTexCoordPointer(2, GL_FLOAT, 0, texcoords); + if (is_yv12) { + mpglClientActiveTexture(GL_TEXTURE1); + mpglEnableClientState(GL_TEXTURE_COORD_ARRAY); + mpglTexCoordPointer(2, GL_FLOAT, 0, texcoords2); + mpglClientActiveTexture(GL_TEXTURE2); + mpglEnableClientState(GL_TEXTURE_COORD_ARRAY); + mpglTexCoordPointer(2, GL_FLOAT, 0, texcoords2); + mpglClientActiveTexture(GL_TEXTURE0); + } + mpglDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + if (is_yv12) { + mpglClientActiveTexture(GL_TEXTURE1); + mpglDisableClientState(GL_TEXTURE_COORD_ARRAY); + mpglClientActiveTexture(GL_TEXTURE2); + mpglDisableClientState(GL_TEXTURE_COORD_ARRAY); + mpglClientActiveTexture(GL_TEXTURE0); + } + mpglDisableClientState(GL_VERTEX_ARRAY); + return; + } + mpglBegin(GL_QUADS); mpglTexCoord2f(tx, ty); if (is_yv12) { @@ -1957,7 +2007,9 @@ static void swapGlBuffers_x11(MPGLContext *ctx) { glXSwapBuffers(mDisplay, vo_window); } +#endif +#if defined(CONFIG_GL_X11) || defined(CONFIG_GL_EGL_X11) static int x11_check_events(void) { return vo_x11_check_events(mDisplay); } @@ -1997,6 +2049,99 @@ #endif +#ifdef CONFIG_GL_EGL_X11 +static EGLDisplay eglDisplay = EGL_NO_DISPLAY; +static EGLSurface eglSurface = EGL_NO_SURFACE; + +/* + * Some genius thought it a good idea to make + * eglGetProcAddress not work for core functions. + * So we have to use a non-portable way that in addition + * might also return symbols from a different library + * that the one providing the current context, great job! + */ +static void *eglgpa(const GLubyte *name) { + void *res = eglGetProcAddress(name); + if (!res) { + void *h = dlopen("/usr/lib/libGLESv1_CM.so", RTLD_LAZY); + res = dlsym(h, name); + dlclose(h); + } + return res; +} + +static int setGlWindow_egl(MPGLContext *ctx) +{ + static const EGLint cfg_attribs[] = { EGL_NONE }; + static const EGLint ctx_attribs[] = { EGL_NONE }; + EGLContext *context = &ctx->context.egl; + Window win = vo_window; + EGLContext new_context = NULL; + EGLConfig eglConfig; + int num_configs; + if (eglDisplay == EGL_NO_DISPLAY) { + eglDisplay = eglGetDisplay(mDisplay); + if (eglDisplay == EGL_NO_DISPLAY) { + mp_msg(MSGT_VO, MSGL_FATAL, "eglGetDisplay failed: 0x%x\n", eglGetError()); + return SET_WINDOW_FAILED; + } + if (!eglInitialize(eglDisplay, NULL, NULL)) { + mp_msg(MSGT_VO, MSGL_FATAL, "eglInitialize failed: 0x%x\n", eglGetError()); + return SET_WINDOW_FAILED; + } + } + if (*context != EGL_NO_CONTEXT) { + eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroyContext(eglDisplay, *context); + eglDestroySurface(eglDisplay, eglSurface); + } + if (!eglChooseConfig(eglDisplay, cfg_attribs, &eglConfig, 1, &num_configs) || + num_configs != 1) + return SET_WINDOW_FAILED; + eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, win, NULL); + if (eglSurface == EGL_NO_SURFACE) + return SET_WINDOW_FAILED; + + new_context = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, ctx_attribs); + if (new_context == EGL_NO_CONTEXT) + return SET_WINDOW_FAILED; + if (!eglMakeCurrent(eglDisplay, eglSurface, eglSurface, new_context)) + return SET_WINDOW_FAILED; + + // set new values + vo_window = win; + vo_x11_update_geometry(); + *context = new_context; + + getFunctions(eglgpa, eglQueryString(eglDisplay, EGL_EXTENSIONS)); + mpglBegin = NULL; + mpglDrawBuffer = NULL; + + // and inform that reinit is necessary + return SET_WINDOW_REINIT; +} + +/** + * \brief free the VisualInfo and GLXContext of an OpenGL context. + * \ingroup glcontext + */ +static void releaseGlContext_egl(MPGLContext *ctx) { + EGLContext *context = &ctx->context.egl; + if (*context != EGL_NO_CONTEXT) + { + mpglFinish(); + eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroyContext(eglDisplay, *context); + } + *context = EGL_NO_CONTEXT; +} + +static void swapGlBuffers_egl(MPGLContext *ctx) { + eglSwapBuffers(eglDisplay, eglSurface); +} + +#endif + static int setGlWindow_dummy(MPGLContext *ctx) { getFunctions(NULL, NULL); return SET_WINDOW_OK; @@ -2026,6 +2171,8 @@ res = init_mpglcontext(ctx, GLTYPE_X11); if (res) return res; res = init_mpglcontext(ctx, GLTYPE_SDL); + if (res) return res; + res = init_mpglcontext(ctx, GLTYPE_EGL_X11); return res; } memset(ctx, 0, sizeof(*ctx)); @@ -2068,6 +2215,18 @@ ctx->fullscreen = vo_sdl_fullscreen; return vo_sdl_init(); #endif +#ifdef CONFIG_GL_EGL_X11 + case GLTYPE_EGL_X11: + ctx->setGlWindow = setGlWindow_egl; + ctx->releaseGlContext = releaseGlContext_egl; + ctx->swapGlBuffers = swapGlBuffers_egl; + ctx->update_xinerama_info = update_xinerama_info; + ctx->border = vo_x11_border; + ctx->check_events = x11_check_events; + ctx->fullscreen = vo_x11_fullscreen; + ctx->ontop = vo_x11_ontop; + return vo_init(); +#endif default: return 0; } diff -r f8c523d09e5e -r 4a507d3a039a libvo/gl_common.h --- a/libvo/gl_common.h Sat Dec 10 20:21:50 2011 +0000 +++ b/libvo/gl_common.h Sat Dec 10 20:55:31 2011 +0000 @@ -40,6 +40,10 @@ #include #include "x11_common.h" #endif +#ifdef CONFIG_GL_EGL_X11 +#include +#include "x11_common.h" +#endif #include // workaround for some gl.h headers @@ -405,6 +409,7 @@ GLTYPE_W32, GLTYPE_X11, GLTYPE_SDL, + GLTYPE_EGL_X11, }; typedef struct MPGLContext { @@ -422,6 +427,9 @@ #ifdef CONFIG_GL_X11 GLXContext x11; #endif +#ifdef CONFIG_GL_EGL_X11 + EGLContext egl; +#endif } context; int (*setGlWindow)(struct MPGLContext *); void (*releaseGlContext)(struct MPGLContext *); diff -r f8c523d09e5e -r 4a507d3a039a libvo/vo_gl.c --- a/libvo/vo_gl.c Sat Dec 10 20:21:50 2011 +0000 +++ b/libvo/vo_gl.c Sat Dec 10 20:55:31 2011 +0000 @@ -547,7 +547,8 @@ mpglDepthMask(GL_FALSE); mpglDisable(GL_CULL_FACE); mpglEnable(gl_target); - mpglDrawBuffer(vo_doublebuffering?GL_BACK:GL_FRONT); + if (mpglDrawBuffer) + mpglDrawBuffer(vo_doublebuffering?GL_BACK:GL_FRONT); mpglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); mp_msg(MSGT_VO, MSGL_V, "[gl] Creating %dx%d texture...\n", @@ -618,6 +619,13 @@ if (glctx.type == GLTYPE_W32 && !vo_w32_config(d_width, d_height, flags)) return -1; #endif +#ifdef CONFIG_GL_EGL_X11 + if (glctx.type == GLTYPE_EGL_X11) { + XVisualInfo vinfo = { .visual = CopyFromParent, .depth = CopyFromParent }; + vo_x11_create_vo_window(&vinfo, vo_dx, vo_dy, d_width, d_height, flags, + CopyFromParent, "gl", title); + } +#endif #ifdef CONFIG_GL_X11 if (glctx.type == GLTYPE_X11) { static int default_glx_attribs[] = {