Procházet zdrojové kódy

Fixes bug #2037, common EGL code for Android and X11

Gabriel Jacobo před 11 roky
rodič
revize
0eeb76d869

+ 1 - 1
Android.mk

@@ -44,6 +44,6 @@ LOCAL_SRC_FILES := \
 	$(wildcard $(LOCAL_PATH)/src/video/android/*.c))
 
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES
-LOCAL_LDLIBS := -ldl -lGLESv1_CM -lGLESv2 -llog
+LOCAL_LDLIBS := -ldl -lGLESv1_CM -lGLESv2 -llog -landroid
 
 include $(BUILD_SHARED_LIBRARY)

+ 13 - 188
android-project/src/org/libsdl/app/SDLActivity.java

@@ -1,11 +1,5 @@
 package org.libsdl.app;
 
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-import javax.microedition.khronos.egl.EGLSurface;
-
 import android.app.*;
 import android.content.*;
 import android.view.*;
@@ -43,13 +37,6 @@ public class SDLActivity extends Activity {
     protected static Thread mAudioThread;
     protected static AudioTrack mAudioTrack;
 
-    // EGL objects
-    protected static EGLContext  mEGLContext;
-    protected static EGLSurface  mEGLSurface;
-    protected static EGLDisplay  mEGLDisplay;
-    protected static EGLConfig   mEGLConfig;
-    protected static int mGLMajor, mGLMinor;
-
     // Load the .so
     static {
         System.loadLibrary("SDL2");
@@ -70,9 +57,7 @@ public class SDLActivity extends Activity {
         mSingleton = this;
 
         // Set up the surface
-        mEGLSurface = EGL10.EGL_NO_SURFACE;
         mSurface = new SDLSurface(getApplication());
-        mEGLContext = EGL10.EGL_NO_CONTEXT;
 
         mLayout = new AbsoluteLayout(this);
         mLayout.addView(mSurface);
@@ -252,29 +237,12 @@ public class SDLActivity extends Activity {
                                             int action, float x, 
                                             float y, float p);
     public static native void onNativeAccel(float x, float y, float z);
-
-    // Java functions called from C
-
-    public static boolean createGLContext(int majorVersion, int minorVersion, int[] attribs) {
-        return initEGL(majorVersion, minorVersion, attribs);
-    }
-    
-    public static void deleteGLContext() {
-        if (SDLActivity.mEGLDisplay != null && SDLActivity.mEGLContext != EGL10.EGL_NO_CONTEXT) {
-            EGL10 egl = (EGL10)EGLContext.getEGL();
-            egl.eglMakeCurrent(SDLActivity.mEGLDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
-            egl.eglDestroyContext(SDLActivity.mEGLDisplay, SDLActivity.mEGLContext);
-            SDLActivity.mEGLContext = EGL10.EGL_NO_CONTEXT;
-
-            if (SDLActivity.mEGLSurface != EGL10.EGL_NO_SURFACE) {
-                egl.eglDestroySurface(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface);
-                SDLActivity.mEGLSurface = EGL10.EGL_NO_SURFACE;
-            }
-        }
-    }
+    public static native void onNativeSurfaceChanged();
+    public static native void onNativeSurfaceDestroyed();
+    public static native void nativeFlipBuffers();
 
     public static void flipBuffers() {
-        flipEGL();
+        SDLActivity.nativeFlipBuffers();
     }
 
     public static boolean setActivityTitle(String title) {
@@ -332,147 +300,9 @@ public class SDLActivity extends Activity {
         // Transfer the task to the main thread as a Runnable
         return mSingleton.commandHandler.post(new ShowTextInputTask(x, y, w, h));
     }
-
-
-    // EGL functions
-    public static boolean initEGL(int majorVersion, int minorVersion, int[] attribs) {
-        try {
-            EGL10 egl = (EGL10)EGLContext.getEGL();
-            
-            if (SDLActivity.mEGLDisplay == null) {
-                SDLActivity.mEGLDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
-                int[] version = new int[2];
-                egl.eglInitialize(SDLActivity.mEGLDisplay, version);
-            }
-            
-            if (SDLActivity.mEGLDisplay != null && SDLActivity.mEGLContext == EGL10.EGL_NO_CONTEXT) {
-                // No current GL context exists, we will create a new one.
-                Log.v("SDL", "Starting up OpenGL ES " + majorVersion + "." + minorVersion);
-                EGLConfig[] configs = new EGLConfig[128];
-                int[] num_config = new int[1];
-                if (!egl.eglChooseConfig(SDLActivity.mEGLDisplay, attribs, configs, 1, num_config) || num_config[0] == 0) {
-                    Log.e("SDL", "No EGL config available");
-                    return false;
-                }
-                EGLConfig config = null;
-                int bestdiff = -1, bitdiff;
-                int[] value = new int[1];
-                
-                // eglChooseConfig returns a number of configurations that match or exceed the requested attribs.
-                // From those, we select the one that matches our requirements more closely
-                Log.v("SDL", "Got " + num_config[0] + " valid modes from egl");
-                for(int i = 0; i < num_config[0]; i++) {
-                    bitdiff = 0;
-                    // Go through some of the attributes and compute the bit difference between what we want and what we get.
-                    for (int j = 0; ; j += 2) {
-                        if (attribs[j] == EGL10.EGL_NONE)
-                            break;
-
-                        if (attribs[j+1] != EGL10.EGL_DONT_CARE && (attribs[j] == EGL10.EGL_RED_SIZE ||
-                            attribs[j] == EGL10.EGL_GREEN_SIZE ||
-                            attribs[j] == EGL10.EGL_BLUE_SIZE ||
-                            attribs[j] == EGL10.EGL_ALPHA_SIZE ||
-                            attribs[j] == EGL10.EGL_DEPTH_SIZE ||
-                            attribs[j] == EGL10.EGL_STENCIL_SIZE)) {
-                            egl.eglGetConfigAttrib(SDLActivity.mEGLDisplay, configs[i], attribs[j], value);
-                            bitdiff += value[0] - attribs[j + 1]; // value is always >= attrib
-                        }
-                    }
-                    
-                    if (bitdiff < bestdiff || bestdiff == -1) {
-                        config = configs[i];
-                        bestdiff = bitdiff;
-                    }
-                    
-                    if (bitdiff == 0) break; // we found an exact match!
-                }
-                
-                Log.d("SDL", "Selected mode with a total bit difference of " + bestdiff);
-
-                SDLActivity.mEGLConfig = config;
-                SDLActivity.mGLMajor = majorVersion;
-                SDLActivity.mGLMinor = minorVersion;
-            }
             
-            return SDLActivity.createEGLSurface();
-
-        } catch(Exception e) {
-            Log.v("SDL", e + "");
-            for (StackTraceElement s : e.getStackTrace()) {
-                Log.v("SDL", s.toString());
-            }
-            return false;
-        }
-    }
-
-    public static boolean createEGLContext() {
-        EGL10 egl = (EGL10)EGLContext.getEGL();
-        int EGL_CONTEXT_CLIENT_VERSION=0x3098;
-        int contextAttrs[] = new int[] { EGL_CONTEXT_CLIENT_VERSION, SDLActivity.mGLMajor, EGL10.EGL_NONE };
-        SDLActivity.mEGLContext = egl.eglCreateContext(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, EGL10.EGL_NO_CONTEXT, contextAttrs);
-        if (SDLActivity.mEGLContext == EGL10.EGL_NO_CONTEXT) {
-            Log.e("SDL", "Couldn't create context");
-            return false;
-        }
-        return true;
-    }
-
-    public static boolean createEGLSurface() {
-        if (SDLActivity.mEGLDisplay != null && SDLActivity.mEGLConfig != null) {
-            EGL10 egl = (EGL10)EGLContext.getEGL();
-            if (SDLActivity.mEGLContext == EGL10.EGL_NO_CONTEXT) createEGLContext();
-
-            if (SDLActivity.mEGLSurface == EGL10.EGL_NO_SURFACE) {
-                Log.v("SDL", "Creating new EGL Surface");
-                SDLActivity.mEGLSurface = egl.eglCreateWindowSurface(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, SDLActivity.mSurface, null);
-                if (SDLActivity.mEGLSurface == EGL10.EGL_NO_SURFACE) {
-                    Log.e("SDL", "Couldn't create surface");
-                    return false;
-                }
-            }
-            else Log.v("SDL", "EGL Surface remains valid");
-
-            if (egl.eglGetCurrentContext() != SDLActivity.mEGLContext) {
-                if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface, SDLActivity.mEGLSurface, SDLActivity.mEGLContext)) {
-                    Log.e("SDL", "Old EGL Context doesnt work, trying with a new one");
-                    // TODO: Notify the user via a message that the old context could not be restored, and that textures need to be manually restored.
-                    createEGLContext();
-                    if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface, SDLActivity.mEGLSurface, SDLActivity.mEGLContext)) {
-                        Log.e("SDL", "Failed making EGL Context current");
-                        return false;
-                    }
-                }
-                else Log.v("SDL", "EGL Context made current");
-            }
-            else Log.v("SDL", "EGL Context remains current");
-
-            return true;
-        } else {
-            Log.e("SDL", "Surface creation failed, display = " + SDLActivity.mEGLDisplay + ", config = " + SDLActivity.mEGLConfig);
-            return false;
-        }
-    }
-
-    // EGL buffer flip
-    public static void flipEGL() {
-        try {
-            EGL10 egl = (EGL10)EGLContext.getEGL();
-
-            egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, null);
-
-            // drawing here
-
-            egl.eglWaitGL();
-
-            egl.eglSwapBuffers(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface);
-
-
-        } catch(Exception e) {
-            Log.v("SDL", "flipEGL(): " + e);
-            for (StackTraceElement s : e.getStackTrace()) {
-                Log.v("SDL", s.toString());
-            }
-        }
+    public static Surface getNativeSurface() {
+        return SDLActivity.mSurface.getNativeSurface();
     }
 
     // Audio
@@ -600,14 +430,16 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
         mWidth = 1.0f;
         mHeight = 1.0f;
     }
+    
+    public Surface getNativeSurface() {
+        return getHolder().getSurface();
+    }
 
     // Called when we have a valid drawing surface
     @Override
     public void surfaceCreated(SurfaceHolder holder) {
         Log.v("SDL", "surfaceCreated()");
         holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
-        // Set mIsSurfaceReady to 'true' *before* any call to handleResume
-        SDLActivity.mIsSurfaceReady = true;
     }
 
     // Called when we lose the surface
@@ -617,16 +449,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
         // Call this *before* setting mIsSurfaceReady to 'false'
         SDLActivity.handlePause();
         SDLActivity.mIsSurfaceReady = false;
-
-        /* We have to clear the current context and destroy the egl surface here
-         * Otherwise there's BAD_NATIVE_WINDOW errors coming from eglCreateWindowSurface on resume
-         * Ref: http://stackoverflow.com/questions/8762589/eglcreatewindowsurface-on-ics-and-switching-from-2d-to-3d
-         */
-        
-        EGL10 egl = (EGL10)EGLContext.getEGL();
-        egl.eglMakeCurrent(SDLActivity.mEGLDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
-        egl.eglDestroySurface(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface);
-        SDLActivity.mEGLSurface = EGL10.EGL_NO_SURFACE;
+        SDLActivity.onNativeSurfaceDestroyed();
     }
 
     // Called when the surface is resized
@@ -687,6 +510,8 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
 
         // Set mIsSurfaceReady to 'true' *before* making a call to handleResume
         SDLActivity.mIsSurfaceReady = true;
+        SDLActivity.onNativeSurfaceChanged();
+
 
         if (SDLActivity.mSDLThread == null) {
             // This is the entry point to the C app.

+ 30 - 25
configure

@@ -20547,9 +20547,9 @@ fi
 CheckOpenGLESX11()
 {
     if test x$enable_video = xyes -a x$enable_video_opengles = xyes; then
-        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenGL ES (EGL) support" >&5
-$as_echo_n "checking for OpenGL ES (EGL) support... " >&6; }
-        video_opengles=no
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EGL support" >&5
+$as_echo_n "checking for EGL support... " >&6; }
+        video_opengl_egl=no
         cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -20566,21 +20566,26 @@ main ()
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
 
-        video_opengles=yes
+        video_opengl_egl=yes
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $video_opengles" >&5
-$as_echo "$video_opengles" >&6; }
-        if test x$video_opengles = xyes; then
-            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenGL ES v1 headers" >&5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $video_opengl_egl" >&5
+$as_echo "$video_opengl_egl" >&6; }
+        if test x$video_opengl_egl = xyes; then
+
+$as_echo "#define SDL_VIDEO_OPENGL_EGL 1" >>confdefs.h
+
+        fi
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenGL ES v1 headers" >&5
 $as_echo_n "checking for OpenGL ES v1 headers... " >&6; }
-            video_opengles_v1=no
-            cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+        video_opengles_v1=no
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-             #include <GLES/gl.h>
-             #include <GLES/glext.h>
+         #include <GLES/gl.h>
+         #include <GLES/glext.h>
 
 int
 main ()
@@ -20593,28 +20598,29 @@ main ()
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
 
-            video_opengles_v1=yes
+        video_opengles_v1=yes
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-            { $as_echo "$as_me:${as_lineno-$LINENO}: result: $video_opengles_v1" >&5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $video_opengles_v1" >&5
 $as_echo "$video_opengles_v1" >&6; }
-            if test x$video_opengles_v1 = xyes; then
+        if test x$video_opengles_v1 = xyes; then
 
 $as_echo "#define SDL_VIDEO_OPENGL_ES 1" >>confdefs.h
 
 
 $as_echo "#define SDL_VIDEO_RENDER_OGL_ES 1" >>confdefs.h
 
-            fi
-            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenGL ES v2 headers" >&5
+        fi
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenGL ES v2 headers" >&5
 $as_echo_n "checking for OpenGL ES v2 headers... " >&6; }
-            video_opengles_v2=no
-            cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+        video_opengles_v2=no
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
-             #include <GLES2/gl2.h>
-             #include <GLES2/gl2ext.h>
+         #include <GLES2/gl2.h>
+         #include <GLES2/gl2ext.h>
 
 int
 main ()
@@ -20627,20 +20633,19 @@ main ()
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
 
-            video_opengles_v2=yes
+        video_opengles_v2=yes
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-            { $as_echo "$as_me:${as_lineno-$LINENO}: result: $video_opengles_v2" >&5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $video_opengles_v2" >&5
 $as_echo "$video_opengles_v2" >&6; }
-            if test x$video_opengles_v2 = xyes; then
+        if test x$video_opengles_v2 = xyes; then
 
 $as_echo "#define SDL_VIDEO_OPENGL_ES2 1" >>confdefs.h
 
 
 $as_echo "#define SDL_VIDEO_RENDER_OGL_ES2 1" >>confdefs.h
 
-            fi
         fi
     fi
 }

+ 36 - 33
configure.in

@@ -1681,44 +1681,47 @@ dnl Find OpenGL ES
 CheckOpenGLESX11()
 {
     if test x$enable_video = xyes -a x$enable_video_opengles = xyes; then
-        AC_MSG_CHECKING(for OpenGL ES (EGL) support)
-        video_opengles=no
+        AC_MSG_CHECKING(for EGL support)
+        video_opengl_egl=no
         AC_TRY_COMPILE([
          #include <EGL/egl.h>
         ],[
         ],[
-        video_opengles=yes
+        video_opengl_egl=yes
         ])
-        AC_MSG_RESULT($video_opengles)
-        if test x$video_opengles = xyes; then
-            AC_MSG_CHECKING(for OpenGL ES v1 headers)
-            video_opengles_v1=no
-            AC_TRY_COMPILE([
-             #include <GLES/gl.h>
-             #include <GLES/glext.h>
-            ],[
-            ],[
-            video_opengles_v1=yes
-            ])
-            AC_MSG_RESULT($video_opengles_v1)
-            if test x$video_opengles_v1 = xyes; then
-                AC_DEFINE(SDL_VIDEO_OPENGL_ES, 1, [ ])
-                AC_DEFINE(SDL_VIDEO_RENDER_OGL_ES, 1, [ ])
-            fi
-            AC_MSG_CHECKING(for OpenGL ES v2 headers)
-            video_opengles_v2=no
-            AC_TRY_COMPILE([
-             #include <GLES2/gl2.h>
-             #include <GLES2/gl2ext.h>
-            ],[
-            ],[
-            video_opengles_v2=yes
-            ])
-            AC_MSG_RESULT($video_opengles_v2)
-            if test x$video_opengles_v2 = xyes; then
-                AC_DEFINE(SDL_VIDEO_OPENGL_ES2, 1, [ ])
-                AC_DEFINE(SDL_VIDEO_RENDER_OGL_ES2, 1, [ ])
-            fi
+        AC_MSG_RESULT($video_opengl_egl)
+        if test x$video_opengl_egl = xyes; then
+            AC_DEFINE(SDL_VIDEO_OPENGL_EGL, 1, [ ])
+        fi
+            
+        AC_MSG_CHECKING(for OpenGL ES v1 headers)
+        video_opengles_v1=no
+        AC_TRY_COMPILE([
+         #include <GLES/gl.h>
+         #include <GLES/glext.h>
+        ],[
+        ],[
+        video_opengles_v1=yes
+        ])
+        AC_MSG_RESULT($video_opengles_v1)
+        if test x$video_opengles_v1 = xyes; then
+            AC_DEFINE(SDL_VIDEO_OPENGL_ES, 1, [ ])
+            AC_DEFINE(SDL_VIDEO_RENDER_OGL_ES, 1, [ ])
+        fi
+        
+        AC_MSG_CHECKING(for OpenGL ES v2 headers)
+        video_opengles_v2=no
+        AC_TRY_COMPILE([
+         #include <GLES2/gl2.h>
+         #include <GLES2/gl2ext.h>
+        ],[
+        ],[
+        video_opengles_v2=yes
+        ])
+        AC_MSG_RESULT($video_opengles_v2)
+        if test x$video_opengles_v2 = xyes; then
+            AC_DEFINE(SDL_VIDEO_OPENGL_ES2, 1, [ ])
+            AC_DEFINE(SDL_VIDEO_RENDER_OGL_ES2, 1, [ ])
         fi
     fi
 }

+ 1 - 0
include/SDL_config.h.in

@@ -290,6 +290,7 @@
 #undef SDL_VIDEO_OPENGL_ES
 #undef SDL_VIDEO_OPENGL_BGL
 #undef SDL_VIDEO_OPENGL_CGL
+#undef SDL_VIDEO_OPENGL_EGL
 #undef SDL_VIDEO_OPENGL_GLX
 #undef SDL_VIDEO_OPENGL_WGL
 #undef SDL_VIDEO_OPENGL_OSMESA

+ 1 - 0
include/SDL_config_android.h

@@ -129,6 +129,7 @@
 
 /* Enable OpenGL ES */
 #define SDL_VIDEO_OPENGL_ES 1
+#define SDL_VIDEO_OPENGL_EGL 1
 #define SDL_VIDEO_RENDER_OGL_ES 1
 #define SDL_VIDEO_RENDER_OGL_ES2    1
 

+ 1 - 1
include/SDL_video.h

@@ -193,7 +193,7 @@ typedef enum
 {
     SDL_GL_CONTEXT_PROFILE_CORE           = 0x0001,
     SDL_GL_CONTEXT_PROFILE_COMPATIBILITY  = 0x0002,
-    SDL_GL_CONTEXT_PROFILE_ES             = 0x0004
+    SDL_GL_CONTEXT_PROFILE_ES             = 0x0004 /* GLX_CONTEXT_ES2_PROFILE_BIT_EXT */
 } SDL_GLprofile;
 
 typedef enum

+ 72 - 45
src/core/android/SDL_android.c

@@ -33,6 +33,7 @@
 #include "../../video/android/SDL_androidkeyboard.h"
 #include "../../video/android/SDL_androidtouch.h"
 #include "../../video/android/SDL_androidvideo.h"
+#include "../../video/android/SDL_androidwindow.h"
 
 #include <android/log.h>
 #include <pthread.h>
@@ -67,8 +68,7 @@ static JavaVM* mJavaVM;
 static jclass mActivityClass;
 
 // method signatures
-static jmethodID midCreateGLContext;
-static jmethodID midDeleteGLContext;
+static jmethodID midGetNativeSurface;
 static jmethodID midFlipBuffers;
 static jmethodID midAudioInit;
 static jmethodID midAudioWriteShortBuffer;
@@ -116,10 +116,8 @@ void SDL_Android_Init(JNIEnv* mEnv, jclass cls)
 
     mActivityClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
 
-    midCreateGLContext = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
-                                "createGLContext","(II[I)Z");
-    midDeleteGLContext = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
-                                "deleteGLContext","()V");
+    midGetNativeSurface = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "getNativeSurface","()Landroid/view/Surface;");
     midFlipBuffers = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
                                 "flipBuffers","()V");
     midAudioInit = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
@@ -133,7 +131,7 @@ void SDL_Android_Init(JNIEnv* mEnv, jclass cls)
 
     bHasNewData = false;
 
-    if(!midCreateGLContext || !midFlipBuffers || !midAudioInit ||
+    if(!midGetNativeSurface || !midFlipBuffers || !midAudioInit ||
        !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioQuit) {
         __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly");
     }
@@ -148,6 +146,65 @@ void Java_org_libsdl_app_SDLActivity_onNativeResize(
     Android_SetScreenResolution(width, height, format);
 }
 
+
+// Surface Created
+void Java_org_libsdl_app_SDLActivity_onNativeSurfaceChanged(JNIEnv* env, jclass jcls)
+{
+    SDL_WindowData *data;
+    SDL_VideoDevice *_this;
+
+    if (Android_Window == NULL || Android_Window->driverdata == NULL ) {
+        return;
+    }
+    
+    _this =  SDL_GetVideoDevice();
+    data =  (SDL_WindowData *) Android_Window->driverdata;
+    
+    /* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */
+    if (data->egl_surface == EGL_NO_SURFACE) {
+        if(data->native_window) {
+            ANativeWindow_release(data->native_window);
+        }
+        data->native_window = Android_JNI_GetNativeWindow();
+        data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->native_window);
+    }
+    
+    /* GL Context handling is done in the event loop because this function is run from the Java thread */
+    
+}
+
+// Surface Destroyed
+void Java_org_libsdl_app_SDLActivity_onNativeSurfaceDestroyed(JNIEnv* env, jclass jcls)
+{
+    /* We have to clear the current context and destroy the egl surface here
+     * Otherwise there's BAD_NATIVE_WINDOW errors coming from eglCreateWindowSurface on resume
+     * Ref: http://stackoverflow.com/questions/8762589/eglcreatewindowsurface-on-ics-and-switching-from-2d-to-3d
+     */
+    SDL_WindowData *data;
+    SDL_VideoDevice *_this;
+    
+    if (Android_Window == NULL || Android_Window->driverdata == NULL ) {
+        return;
+    }
+    
+    _this =  SDL_GetVideoDevice();
+    data = (SDL_WindowData *) Android_Window->driverdata;
+    
+    if (data->egl_surface != EGL_NO_SURFACE) {
+        SDL_EGL_MakeCurrent(_this, NULL, NULL);
+        SDL_EGL_DestroySurface(_this, data->egl_surface);
+        data->egl_surface = EGL_NO_SURFACE;
+    }
+    
+    /* GL Context handling is done in the event loop because this function is run from the Java thread */
+
+}
+
+void Java_org_libsdl_app_SDLActivity_nativeFlipBuffers(JNIEnv* env, jclass jcls)
+{
+    SDL_GL_SwapWindow(Android_Window);
+}
+
 // Keydown
 void Java_org_libsdl_app_SDLActivity_onNativeKeyDown(
                                     JNIEnv* env, jclass jcls, jint keycode)
@@ -317,47 +374,17 @@ static SDL_bool LocalReferenceHolder_IsActive()
     return s_active > 0;    
 }
 
-
-SDL_bool Android_JNI_CreateContext(int majorVersion, int minorVersion,
-                                int red, int green, int blue, int alpha,
-                                int buffer, int depth, int stencil,
-                                int buffers, int samples)
+ANativeWindow* Android_JNI_GetNativeWindow(void)
 {
+    ANativeWindow* anw;
+    jobject s;
     JNIEnv *env = Android_JNI_GetEnv();
 
-    jint attribs[] = {
-        EGL_RED_SIZE, red,
-        EGL_GREEN_SIZE, green,
-        EGL_BLUE_SIZE, blue,
-        EGL_ALPHA_SIZE, alpha,
-        EGL_BUFFER_SIZE, buffer,
-        EGL_DEPTH_SIZE, depth,
-        EGL_STENCIL_SIZE, stencil,
-        EGL_SAMPLE_BUFFERS, buffers,
-        EGL_SAMPLES, samples,
-        EGL_RENDERABLE_TYPE, (majorVersion == 1 ? EGL_OPENGL_ES_BIT : EGL_OPENGL_ES2_BIT),
-        EGL_NONE
-    };
-    int len = SDL_arraysize(attribs);
-
-    jintArray array;
-
-    array = (*env)->NewIntArray(env, len);
-    (*env)->SetIntArrayRegion(env, array, 0, len, attribs);
-
-    jboolean success = (*env)->CallStaticBooleanMethod(env, mActivityClass, midCreateGLContext, majorVersion, minorVersion, array);
-
-    (*env)->DeleteLocalRef(env, array);
-
-    return success ? SDL_TRUE : SDL_FALSE;
-}
-
-SDL_bool Android_JNI_DeleteContext(void)
-{
-    /* There's only one context, so no parameter for now */
-    JNIEnv *env = Android_JNI_GetEnv();
-    (*env)->CallStaticVoidMethod(env, mActivityClass, midDeleteGLContext);
-    return SDL_TRUE;
+    s = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetNativeSurface);
+    anw = ANativeWindow_fromSurface(env, s);
+    (*env)->DeleteLocalRef(env, s);
+  
+    return anw;
 }
 
 void Android_JNI_SwapWindow()

+ 6 - 2
src/core/android/SDL_android.h

@@ -27,16 +27,20 @@ extern "C" {
 /* *INDENT-ON* */
 #endif
 
+#include <EGL/eglplatform.h>
+#include <android/native_window_jni.h>
+
 #include "SDL_rect.h"
 
 /* Interface from the SDL library into the Android Java activity */
-extern SDL_bool Android_JNI_CreateContext(int majorVersion, int minorVersion, int red, int green, int blue, int alpha, int buffer, int depth, int stencil, int buffers, int samples);
-extern SDL_bool Android_JNI_DeleteContext(void);
+/*extern SDL_bool Android_JNI_CreateContext(int majorVersion, int minorVersion, int red, int green, int blue, int alpha, int buffer, int depth, int stencil, int buffers, int samples);
+extern SDL_bool Android_JNI_DeleteContext(void);*/
 extern void Android_JNI_SwapWindow();
 extern void Android_JNI_SetActivityTitle(const char *title);
 extern SDL_bool Android_JNI_GetAccelerometerValues(float values[3]);
 extern void Android_JNI_ShowTextInput(SDL_Rect *inputRect);
 extern void Android_JNI_HideTextInput();
+extern ANativeWindow* Android_JNI_GetNativeWindow(void);
 
 /* Audio support */
 extern int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames);

+ 407 - 0
src/video/SDL_egl.c

@@ -0,0 +1,407 @@
+/*
+ *  Simple DirectMedia Layer
+ *  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+ * 
+ *  This software is provided 'as-is', without any express or implied
+ *  warranty.  In no event will the authors be held liable for any damages
+ *  arising from the use of this software.
+ * 
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute it
+ *  freely, subject to the following restrictions:
+ * 
+ *  1. The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *  2. Altered source versions must be plainly marked as such, and must not be
+ *     misrepresented as being the original software.
+ *  3. This notice may not be removed or altered from any source distribution.
+ */
+#include "SDL_config.h"
+
+#if SDL_VIDEO_OPENGL_EGL
+
+#include "SDL_sysvideo.h"
+#include "SDL_egl.h"
+
+#define DEFAULT_EGL "libEGL.so"
+#define DEFAULT_OGL_ES2 "libGLESv2.so"
+#define DEFAULT_OGL_ES_PVR "libGLES_CM.so"
+#define DEFAULT_OGL_ES "libGLESv1_CM.so"
+
+#define LOAD_FUNC(NAME) \
+*((void**)&_this->egl_data->NAME) = dlsym(handle, #NAME); \
+if (!_this->egl_data->NAME) \
+{ \
+    return SDL_SetError("Could not retrieve EGL function " #NAME); \
+}
+    
+/* EGL implementation of SDL OpenGL ES support */
+
+void *
+SDL_EGL_GetProcAddress(_THIS, const char *proc)
+{
+    static char procname[1024];
+    void *handle;
+    void *retval;
+    
+    /* eglGetProcAddress is busted on Android http://code.google.com/p/android/issues/detail?id=7681 */
+#if !defined(SDL_VIDEO_DRIVER_ANDROID)
+    handle = _this->egl_data->egl_dll_handle;
+    if (_this->egl_data->eglGetProcAddress) {
+        retval = _this->egl_data->eglGetProcAddress(proc);
+        if (retval) {
+            return retval;
+        }
+    }
+#endif
+    
+    handle = _this->gl_config.dll_handle;
+    #if defined(__OpenBSD__) && !defined(__ELF__)
+    #undef dlsym(x,y);
+    #endif
+    retval = dlsym(handle, proc);
+    if (!retval && strlen(proc) <= 1022) {
+        procname[0] = '_';
+        strcpy(procname + 1, proc);
+        retval = dlsym(handle, procname);
+    }
+    return retval;
+}
+
+void
+SDL_EGL_UnloadLibrary(_THIS)
+{
+    if ((_this->egl_data) && (_this->gl_config.driver_loaded)) {
+        _this->egl_data->eglTerminate(_this->egl_data->egl_display);
+        
+        dlclose(_this->gl_config.dll_handle);
+        dlclose(_this->egl_data->egl_dll_handle);
+        
+        SDL_free(_this->egl_data);
+        _this->egl_data = NULL;
+        
+        _this->gl_config.dll_handle = NULL;
+        _this->gl_config.driver_loaded = 0;
+    }
+}
+
+int
+SDL_EGL_LoadLibrary(_THIS, const char *path, NativeDisplayType native_display)
+{
+    void *handle;
+    int dlopen_flags;
+    
+    if (_this->egl_data) {
+        return SDL_SetError("OpenGL ES context already created");
+    }
+    
+    /* Unload the old driver and reset the pointers */
+    SDL_EGL_UnloadLibrary(_this);
+    
+    #ifdef RTLD_GLOBAL
+    dlopen_flags = RTLD_LAZY | RTLD_GLOBAL;
+    #else
+    dlopen_flags = RTLD_LAZY;
+    #endif
+    handle = dlopen(path, dlopen_flags);
+    /* Catch the case where the application isn't linked with EGL */
+    if ((dlsym(handle, "eglChooseConfig") == NULL) && (path == NULL)) {
+        
+        dlclose(handle);
+        path = getenv("SDL_VIDEO_EGL_DRIVER");
+        if (path == NULL) {
+            path = DEFAULT_EGL;
+        }
+        handle = dlopen(path, dlopen_flags);
+    }
+
+    if (handle == NULL) {
+        return SDL_SetError("Could not load OpenGL ES/EGL library");
+    }
+    
+    _this->egl_data = (struct SDL_EGL_VideoData *) SDL_calloc(1, sizeof(SDL_EGL_VideoData));
+    if (!_this->egl_data) {
+        return SDL_OutOfMemory();
+    }
+    
+    /* Load new function pointers */
+    LOAD_FUNC(eglGetDisplay);
+    LOAD_FUNC(eglInitialize);
+    LOAD_FUNC(eglTerminate);
+    LOAD_FUNC(eglGetProcAddress);
+    LOAD_FUNC(eglChooseConfig);
+    LOAD_FUNC(eglGetConfigAttrib);
+    LOAD_FUNC(eglCreateContext);
+    LOAD_FUNC(eglDestroyContext);
+    LOAD_FUNC(eglCreateWindowSurface);
+    LOAD_FUNC(eglDestroySurface);
+    LOAD_FUNC(eglMakeCurrent);
+    LOAD_FUNC(eglSwapBuffers);
+    LOAD_FUNC(eglSwapInterval);
+    LOAD_FUNC(eglWaitNative);
+    LOAD_FUNC(eglWaitGL);
+    
+    _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
+    
+    if (!_this->egl_data->egl_display) {
+        return SDL_SetError("Could not get EGL display");
+    }
+    
+    if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
+        return SDL_SetError("Could not initialize EGL");
+    }
+
+    _this->egl_data->egl_dll_handle = handle;
+
+    path = getenv("SDL_VIDEO_GL_DRIVER");
+    handle = dlopen(path, dlopen_flags);
+    if ((path == NULL) | (handle == NULL)) {
+      if (_this->gl_config.major_version > 1) {
+          path = DEFAULT_OGL_ES2;
+          handle = dlopen(path, dlopen_flags);
+      } else {
+          path = DEFAULT_OGL_ES;
+          handle = dlopen(path, dlopen_flags);
+          if (handle == NULL) {
+              path = DEFAULT_OGL_ES_PVR;
+              handle = dlopen(path, dlopen_flags);
+          }
+      }
+    }
+
+    if (handle == NULL) {
+      return SDL_SetError("Could not initialize OpenGL ES library");
+    }
+
+    _this->gl_config.dll_handle = handle;
+    _this->gl_config.driver_loaded = 1;
+
+    if (path) {
+      strncpy(_this->gl_config.driver_path, path,
+              sizeof(_this->gl_config.driver_path) - 1);
+    } else {
+      strcpy(_this->gl_config.driver_path, "");
+    }
+    
+    /* We need to select a config here to satisfy some video backends such as X11 */
+    SDL_EGL_ChooseConfig(_this);
+    
+    return 0;
+}
+
+int
+SDL_EGL_ChooseConfig(_THIS) 
+{
+    /* 64 seems nice. */
+    EGLint attribs[64];
+    EGLint found_configs = 0;
+    int i;
+    
+    if (!_this->egl_data) {
+        /* The EGL library wasn't loaded, SDL_GetError() should have info */
+        return -1;
+    }
+  
+    /* Get a valid EGL configuration */
+    i = 0;
+    attribs[i++] = EGL_RED_SIZE;
+    attribs[i++] = _this->gl_config.red_size;
+    attribs[i++] = EGL_GREEN_SIZE;
+    attribs[i++] = _this->gl_config.green_size;
+    attribs[i++] = EGL_BLUE_SIZE;
+    attribs[i++] = _this->gl_config.blue_size;
+    
+    if (_this->gl_config.alpha_size) {
+        attribs[i++] = EGL_ALPHA_SIZE;
+        attribs[i++] = _this->gl_config.alpha_size;
+    }
+    
+    if (_this->gl_config.buffer_size) {
+        attribs[i++] = EGL_BUFFER_SIZE;
+        attribs[i++] = _this->gl_config.buffer_size;
+    }
+    
+    attribs[i++] = EGL_DEPTH_SIZE;
+    attribs[i++] = _this->gl_config.depth_size;
+    
+    if (_this->gl_config.stencil_size) {
+        attribs[i++] = EGL_STENCIL_SIZE;
+        attribs[i++] = _this->gl_config.stencil_size;
+    }
+    
+    if (_this->gl_config.multisamplebuffers) {
+        attribs[i++] = EGL_SAMPLE_BUFFERS;
+        attribs[i++] = _this->gl_config.multisamplebuffers;
+    }
+    
+    if (_this->gl_config.multisamplesamples) {
+        attribs[i++] = EGL_SAMPLES;
+        attribs[i++] = _this->gl_config.multisamplesamples;
+    }
+    
+    attribs[i++] = EGL_RENDERABLE_TYPE;
+    if (_this->gl_config.major_version == 2) {
+        attribs[i++] = EGL_OPENGL_ES2_BIT;
+    } else {
+        attribs[i++] = EGL_OPENGL_ES_BIT;
+    }
+    
+    attribs[i++] = EGL_NONE;
+    
+    if (_this->egl_data->eglChooseConfig(_this->egl_data->egl_display,
+        attribs,
+        &_this->egl_data->egl_config, 1,
+        &found_configs) == EGL_FALSE ||
+        found_configs == 0) {
+        return SDL_SetError("Couldn't find matching EGL config");
+    }
+    
+    return 0;
+}
+
+SDL_GLContext
+SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface)
+{
+    EGLint context_attrib_list[] = {
+        EGL_CONTEXT_CLIENT_VERSION,
+        1,
+        EGL_NONE
+    };
+    
+    EGLContext egl_context;
+    
+    if (!_this->egl_data) {
+        /* The EGL library wasn't loaded, SDL_GetError() should have info */
+        return NULL;
+    }
+    
+    if (_this->gl_config.major_version) {
+        context_attrib_list[1] = _this->gl_config.major_version;
+    }
+
+    egl_context =
+    _this->egl_data->eglCreateContext(_this->egl_data->egl_display,
+                                      _this->egl_data->egl_config,
+                                      EGL_NO_CONTEXT, context_attrib_list);
+    
+    if (egl_context == EGL_NO_CONTEXT) {
+        SDL_SetError("Could not create EGL context");
+        return NULL;
+    }
+    
+    _this->egl_data->egl_swapinterval = 0;
+    
+    if (SDL_EGL_MakeCurrent(_this, egl_surface, egl_context) < 0) {
+        SDL_EGL_DeleteContext(_this, egl_context);
+        SDL_SetError("Could not make EGL context current");
+        return NULL;
+    }
+  
+    return (SDL_GLContext) egl_context;
+}
+
+int
+SDL_EGL_MakeCurrent(_THIS, EGLSurface egl_surface, SDL_GLContext context)
+{
+    if (!_this->egl_data) {
+        return SDL_SetError("OpenGL not initialized");
+    }
+    
+    EGLContext egl_context = (EGLContext) context;
+    
+    /* The android emulator crashes badly if you try to eglMakeCurrent 
+     * with a valid context and invalid surface, so we have to check for both here.
+     */
+    if (!egl_context || !egl_surface) {
+         _this->egl_data->eglMakeCurrent(_this->egl_data->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    }
+    else {
+        if (!_this->egl_data->eglMakeCurrent(_this->egl_data->egl_display,
+            egl_surface, egl_surface, egl_context)) {
+            return SDL_SetError("Unable to make EGL context current");
+        }
+    }
+      
+    return 0;
+}
+
+int
+SDL_EGL_SetSwapInterval(_THIS, int interval)
+{
+    if (_this->egl_data) {
+        return SDL_SetError("OpenGL ES context not active");
+    }
+    
+    EGLBoolean status;
+    status = _this->egl_data->eglSwapInterval(_this->egl_data->egl_display, interval);
+    if (status == EGL_TRUE) {
+        _this->egl_data->egl_swapinterval = interval;
+        return 0;
+    }
+    
+    return SDL_SetError("Unable to set the EGL swap interval");
+}
+
+int
+SDL_EGL_GetSwapInterval(_THIS)
+{
+    if (_this->egl_data) {
+        return SDL_SetError("OpenGL ES context not active");
+    }
+    
+    return _this->egl_data->egl_swapinterval;
+}
+
+void
+SDL_EGL_SwapBuffers(_THIS, EGLSurface egl_surface)
+{
+    _this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, egl_surface);
+}
+
+void
+SDL_EGL_DeleteContext(_THIS, SDL_GLContext context)
+{
+    /* Clean up GLES and EGL */
+    if (!_this->egl_data) {
+        return;
+    }
+    
+    EGLContext egl_context = (EGLContext) context;
+    
+    if (!egl_context && egl_context != EGL_NO_CONTEXT) {
+        SDL_EGL_MakeCurrent(_this, NULL, NULL);
+        _this->egl_data->eglDestroyContext(_this->egl_data->egl_display, egl_context);
+    }
+        
+    /* FIXME: This "crappy fix" comes from the X11 code, 
+     * it's required so you can create a GLX context, destroy it and create a EGL one */
+    SDL_EGL_UnloadLibrary(_this);
+}
+
+EGLSurface *
+SDL_EGL_CreateSurface(_THIS, NativeWindowType nw) 
+{
+    return _this->egl_data->eglCreateWindowSurface(
+            _this->egl_data->egl_display,
+            _this->egl_data->egl_config,
+            nw, NULL);
+}
+
+void
+SDL_EGL_DestroySurface(_THIS, EGLSurface egl_surface) 
+{
+    if (!_this->egl_data) {
+        return;
+    }
+    
+    if (egl_surface != EGL_NO_SURFACE) {
+        _this->egl_data->eglDestroySurface(_this->egl_data->egl_display, egl_surface);
+    }
+}
+
+#endif /* SDL_VIDEO_OPENGL_EGL */
+
+/* vi: set ts=4 sw=4 expandtab: */
+    

+ 132 - 0
src/video/SDL_egl.h

@@ -0,0 +1,132 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_config.h"
+
+#ifndef _SDL_egl_h
+#define _SDL_egl_h
+
+#if SDL_VIDEO_OPENGL_EGL
+
+#include <EGL/egl.h>
+
+#include <dlfcn.h>
+#if defined(__OpenBSD__) && !defined(__ELF__)
+#define dlsym(x,y) dlsym(x, "_" y)
+#endif
+
+#include "SDL_sysvideo.h"
+
+typedef struct SDL_EGL_VideoData
+{
+    void *egl_dll_handle;
+    EGLDisplay egl_display;
+    EGLConfig egl_config;
+    int egl_swapinterval;
+    
+    EGLDisplay(*eglGetDisplay) (NativeDisplayType display);
+    EGLBoolean(*eglInitialize) (EGLDisplay dpy, EGLint * major,
+                                EGLint * minor);
+    EGLBoolean(*eglTerminate) (EGLDisplay dpy);
+    
+    void *(*eglGetProcAddress) (const char * procName);
+    
+    EGLBoolean(*eglChooseConfig) (EGLDisplay dpy,
+                                  const EGLint * attrib_list,
+                                  EGLConfig * configs,
+                                  EGLint config_size, EGLint * num_config);
+    
+    EGLContext(*eglCreateContext) (EGLDisplay dpy,
+                                   EGLConfig config,
+                                   EGLContext share_list,
+                                   const EGLint * attrib_list);
+    
+    EGLBoolean(*eglDestroyContext) (EGLDisplay dpy, EGLContext ctx);
+    
+    EGLSurface(*eglCreateWindowSurface) (EGLDisplay dpy,
+                                         EGLConfig config,
+                                         NativeWindowType window,
+                                         const EGLint * attrib_list);
+    EGLBoolean(*eglDestroySurface) (EGLDisplay dpy, EGLSurface surface);
+    
+    EGLBoolean(*eglMakeCurrent) (EGLDisplay dpy, EGLSurface draw,
+                                 EGLSurface read, EGLContext ctx);
+    
+    EGLBoolean(*eglSwapBuffers) (EGLDisplay dpy, EGLSurface draw);
+    
+    EGLBoolean(*eglSwapInterval) (EGLDisplay dpy, EGLint interval);
+    
+    const char *(*eglQueryString) (EGLDisplay dpy, EGLint name);
+    
+    EGLBoolean(*eglGetConfigAttrib) (EGLDisplay dpy, EGLConfig config,
+                                     EGLint attribute, EGLint * value);
+    
+    EGLBoolean(*eglWaitNative) (EGLint  engine);
+
+    EGLBoolean(*eglWaitGL)(void);   
+} SDL_EGL_VideoData;
+
+/* OpenGLES functions */
+extern int SDL_EGL_GetAttribute(_THIS, SDL_GLattr attrib, int *value);
+extern int SDL_EGL_LoadLibrary(_THIS, const char *path, NativeDisplayType native_display);
+extern void *SDL_EGL_GetProcAddress(_THIS, const char *proc);
+extern void SDL_EGL_UnloadLibrary(_THIS);
+extern int SDL_EGL_ChooseConfig(_THIS);
+extern int SDL_EGL_SetSwapInterval(_THIS, int interval);
+extern int SDL_EGL_GetSwapInterval(_THIS);
+extern void SDL_EGL_DeleteContext(_THIS, SDL_GLContext context);
+extern EGLSurface *SDL_EGL_CreateSurface(_THIS, NativeWindowType nw);
+extern void SDL_EGL_DestroySurface(_THIS, EGLSurface egl_surface);
+
+/* These need to be wrapped to get the surface for the window by the platform GLES implementation */
+extern SDL_GLContext SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface);
+extern int SDL_EGL_MakeCurrent(_THIS, EGLSurface egl_surface, SDL_GLContext context);
+extern void SDL_EGL_SwapBuffers(_THIS, EGLSurface egl_surface);
+
+/* A few of useful macros */
+
+#define SDL_EGL_SwapWindow_impl(BACKEND) void \
+BACKEND ## _GLES_SwapWindow(_THIS, SDL_Window * window) \
+{\
+    SDL_EGL_SwapBuffers(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);\
+}
+
+#define SDL_EGL_MakeCurrent_impl(BACKEND) int \
+BACKEND ## _GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) \
+{\
+    if (window && context) { \
+        return SDL_EGL_MakeCurrent(_this, ((SDL_WindowData *) window->driverdata)->egl_surface, context); \
+    }\
+    else {\
+        return SDL_EGL_MakeCurrent(_this, NULL, NULL);\
+    }\
+}
+
+#define SDL_EGL_CreateContext_impl(BACKEND) SDL_GLContext \
+BACKEND ## _GLES_CreateContext(_THIS, SDL_Window * window) \
+{\
+    return SDL_EGL_CreateContext(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);\
+}
+
+#endif /* SDL_VIDEO_OPENGL_EGL */
+
+#endif /* _SDL_egl_h */
+
+/* vi: set ts=4 sw=4 expandtab: */

+ 5 - 1
src/video/SDL_sysvideo.h

@@ -313,7 +313,11 @@ struct SDL_VideoDevice
     /* Data private to this driver */
     void *driverdata;
     struct SDL_GLDriverData *gl_data;
-
+    
+#if SDL_VIDEO_OPENGL_EGL
+    struct SDL_EGL_VideoData *egl_data;
+#endif
+    
 #if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
     struct SDL_PrivateGLESData *gles_data;
 #endif

+ 5 - 0
src/video/SDL_video.c

@@ -487,11 +487,16 @@ SDL_VideoInit(const char *driver_name)
 #elif SDL_VIDEO_OPENGL_ES
     _this->gl_config.major_version = 1;
     _this->gl_config.minor_version = 1;
+#if SDL_VIDEO_OPENGL_EGL    
     _this->gl_config.use_egl = 1;
+#endif    
 #elif SDL_VIDEO_OPENGL_ES2
     _this->gl_config.major_version = 2;
     _this->gl_config.minor_version = 0;
+#if SDL_VIDEO_OPENGL_EGL    
     _this->gl_config.use_egl = 1;
+#endif
+    
 #endif
     _this->gl_config.flags = 0;
     _this->gl_config.profile_mask = 0;

+ 31 - 8
src/video/android/SDL_androidevents.c

@@ -27,6 +27,32 @@
 
 #include "SDL_androidevents.h"
 #include "SDL_events.h"
+#include "SDL_androidwindow.h"
+
+void android_egl_context_backup();
+void android_egl_context_restore();
+
+void 
+android_egl_context_restore() 
+{
+    SDL_WindowData *data = (SDL_WindowData *) Android_Window->driverdata;
+    if (SDL_GL_MakeCurrent(Android_Window, (SDL_GLContext) data->egl_context) < 0) {
+        /* The context is no longer valid, create a new one */
+        /* FIXME: Notify the user that the context changed and textures need to be re created*/
+        data->egl_context = (EGLContext) SDL_GL_CreateContext(Android_Window);
+        SDL_GL_MakeCurrent(Android_Window, (SDL_GLContext) data->egl_context);
+    }
+}
+
+void 
+android_egl_context_backup() 
+{
+    /* Keep a copy of the EGL Context so we can try to restore it when we resume */
+    SDL_WindowData *data = (SDL_WindowData *) Android_Window->driverdata;
+    data->egl_context = SDL_GL_GetCurrentContext();
+    /* We need to do this so the EGLSurface can be freed */
+    SDL_GL_MakeCurrent(Android_Window, NULL);
+}
 
 void
 Android_PumpEvents(_THIS)
@@ -52,13 +78,9 @@ Android_PumpEvents(_THIS)
         if(SDL_SemTryWait(Android_ResumeSem) == 0) {
 #endif
             isPaused = 0;
-            /* TODO: Should we double check if we are on the same thread as the one that made the original GL context?
-             * This call will go through the following chain of calls in Java:
-             * SDLActivity::createGLContext -> SDLActivity:: initEGL -> SDLActivity::createEGLSurface -> SDLActivity::createEGLContext
-             * SDLActivity::createEGLContext will attempt to restore the GL context first, and if that fails it will create a new one
-             * If a new GL context is created, the user needs to restore the textures manually (TODO: notify the user that this happened with a message)
-             */
-            SDL_GL_CreateContext(Android_Window);
+            
+            /* Restore the GL Context from here, as this operation is thread dependent */
+            android_egl_context_restore();
         }
     }
     else {
@@ -70,13 +92,14 @@ Android_PumpEvents(_THIS)
                 isPausing = 1;
             }
             else {
+                android_egl_context_backup();
                 isPausing = 0;
                 isPaused = 1;
             }
         }
 #else
         if(SDL_SemTryWait(Android_PauseSem) == 0) {
-            /* If we fall in here, the system is/was paused */
+            android_egl_context_backup();
             isPaused = 1;
         }
 #endif

+ 11 - 84
src/video/android/SDL_androidgl.c

@@ -25,6 +25,8 @@
 /* Android SDL video driver implementation */
 
 #include "SDL_video.h"
+#include "../SDL_egl.h"
+#include "SDL_androidwindow.h"
 
 #include "SDL_androidvideo.h"
 #include "../../core/android/SDL_android.h"
@@ -33,95 +35,20 @@
 
 #include <dlfcn.h>
 
-static void* Android_GLHandle = NULL;
+SDL_EGL_CreateContext_impl(Android)
+SDL_EGL_MakeCurrent_impl(Android)
 
-/* GL functions */
-int
-Android_GL_LoadLibrary(_THIS, const char *path)
-{
-    if (!Android_GLHandle) {
-        Android_GLHandle = dlopen("libGLESv1_CM.so",RTLD_GLOBAL);
-        if (!Android_GLHandle) {
-            return SDL_SetError("Could not initialize GL ES library\n");
-        }
-    }
-    return 0;
-}
-
-void *
-Android_GL_GetProcAddress(_THIS, const char *proc)
-{
-    /*
-       !!! FIXME: this _should_ use eglGetProcAddress(), but it appears to be
-       !!! FIXME:  busted on Android at the moment...
-       !!! FIXME:  http://code.google.com/p/android/issues/detail?id=7681
-       !!! FIXME: ...so revisit this later.  --ryan.
-    */
-    return dlsym(Android_GLHandle, proc);
-}
-
-void
-Android_GL_UnloadLibrary(_THIS)
+Android_GLES_SwapWindow(_THIS, SDL_Window * window)
 {
-    if(Android_GLHandle) {
-        dlclose(Android_GLHandle);
-        Android_GLHandle = NULL;
-    }
-}
-
-SDL_GLContext
-Android_GL_CreateContext(_THIS, SDL_Window * window)
-{
-    if (!Android_JNI_CreateContext(_this->gl_config.major_version,
-                                   _this->gl_config.minor_version,
-                                   _this->gl_config.red_size,
-                                   _this->gl_config.green_size,
-                                   _this->gl_config.blue_size,
-                                   _this->gl_config.alpha_size,
-                                   _this->gl_config.buffer_size,
-                                   _this->gl_config.depth_size,
-                                   _this->gl_config.stencil_size,
-                                   _this->gl_config.multisamplebuffers,
-                                   _this->gl_config.multisamplesamples)) {
-        SDL_SetError("Couldn't create OpenGL context - see Android log for details");
-        return NULL;
-    }
-    return (SDL_GLContext)1;
+    /* FIXME: These two functions were in the Java code, do we really need them? */
+    _this->egl_data->eglWaitNative(EGL_CORE_NATIVE_ENGINE);
+    _this->egl_data->eglWaitGL();
+    SDL_EGL_SwapBuffers(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
 }
 
 int
-Android_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
-{
-    /* There's only one context, nothing to do... */
-    return 0;
-}
-
-int
-Android_GL_SetSwapInterval(_THIS, int interval)
-{
-    __android_log_print(ANDROID_LOG_INFO, "SDL", "[STUB] GL_SetSwapInterval\n");
-    return 0;
-}
-
-int
-Android_GL_GetSwapInterval(_THIS)
-{
-    __android_log_print(ANDROID_LOG_INFO, "SDL", "[STUB] GL_GetSwapInterval\n");
-    return 0;
-}
-
-void
-Android_GL_SwapWindow(_THIS, SDL_Window * window)
-{
-    Android_JNI_SwapWindow();
-}
-
-void
-Android_GL_DeleteContext(_THIS, SDL_GLContext context)
-{
-    if (context) {
-        Android_JNI_DeleteContext();
-    }
+Android_GLES_LoadLibrary(_THIS, const char *path) {
+    return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) 0);
 }
 
 #endif /* SDL_VIDEO_DRIVER_ANDROID */

+ 19 - 19
src/video/android/SDL_androidvideo.c

@@ -44,17 +44,17 @@
 static int Android_VideoInit(_THIS);
 static void Android_VideoQuit(_THIS);
 
+#include "../SDL_egl.h"
 /* GL functions (SDL_androidgl.c) */
-extern int Android_GL_LoadLibrary(_THIS, const char *path);
-extern void *Android_GL_GetProcAddress(_THIS, const char *proc);
-extern void Android_GL_UnloadLibrary(_THIS);
-extern SDL_GLContext Android_GL_CreateContext(_THIS, SDL_Window * window);
-extern int Android_GL_MakeCurrent(_THIS, SDL_Window * window,
-                              SDL_GLContext context);
-extern int Android_GL_SetSwapInterval(_THIS, int interval);
-extern int Android_GL_GetSwapInterval(_THIS);
-extern void Android_GL_SwapWindow(_THIS, SDL_Window * window);
-extern void Android_GL_DeleteContext(_THIS, SDL_GLContext context);
+extern SDL_GLContext Android_GLES_CreateContext(_THIS, SDL_Window * window);
+extern int Android_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
+extern void Android_GLES_SwapWindow(_THIS, SDL_Window * window);
+extern int Android_GLES_LoadLibrary(_THIS, const char *path);
+#define Android_GLES_GetProcAddress SDL_EGL_GetProcAddress
+#define Android_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
+#define Android_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
+#define Android_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
+#define Android_GLES_DeleteContext SDL_EGL_DeleteContext
 
 /* Android driver bootstrap functions */
 
@@ -114,15 +114,15 @@ Android_CreateDevice(int devindex)
     device->free = Android_DeleteDevice;
 
     /* GL pointers */
-    device->GL_LoadLibrary = Android_GL_LoadLibrary;
-    device->GL_GetProcAddress = Android_GL_GetProcAddress;
-    device->GL_UnloadLibrary = Android_GL_UnloadLibrary;
-    device->GL_CreateContext = Android_GL_CreateContext;
-    device->GL_MakeCurrent = Android_GL_MakeCurrent;
-    device->GL_SetSwapInterval = Android_GL_SetSwapInterval;
-    device->GL_GetSwapInterval = Android_GL_GetSwapInterval;
-    device->GL_SwapWindow = Android_GL_SwapWindow;
-    device->GL_DeleteContext = Android_GL_DeleteContext;
+    device->GL_LoadLibrary = Android_GLES_LoadLibrary;
+    device->GL_GetProcAddress = Android_GLES_GetProcAddress;
+    device->GL_UnloadLibrary = Android_GLES_UnloadLibrary;
+    device->GL_CreateContext = Android_GLES_CreateContext;
+    device->GL_MakeCurrent = Android_GLES_MakeCurrent;
+    device->GL_SetSwapInterval = Android_GLES_SetSwapInterval;
+    device->GL_GetSwapInterval = Android_GLES_GetSwapInterval;
+    device->GL_SwapWindow = Android_GLES_SwapWindow;
+    device->GL_DeleteContext = Android_GLES_DeleteContext;
 
     /* Text input */
     device->StartTextInput = Android_StartTextInput;

+ 36 - 3
src/video/android/SDL_androidwindow.c

@@ -29,15 +29,15 @@
 #include "SDL_androidvideo.h"
 #include "SDL_androidwindow.h"
 
-#include "../../core/android/SDL_android.h"
-
 int
 Android_CreateWindow(_THIS, SDL_Window * window)
 {
+    SDL_WindowData *data;
+    
     if (Android_Window) {
         return SDL_SetError("Android only supports one window");
     }
-    Android_Window = window;
+    
     Android_PauseSem = SDL_CreateSemaphore(0);
     Android_ResumeSem = SDL_CreateSemaphore(0);
 
@@ -56,7 +56,29 @@ Android_CreateWindow(_THIS, SDL_Window * window)
     /* One window, it always has focus */
     SDL_SetMouseFocus(window);
     SDL_SetKeyboardFocus(window);
+    
+    data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
+    if (!data) {
+        return SDL_OutOfMemory();
+    }
+    
+    data->native_window = Android_JNI_GetNativeWindow();
+    
+    if (!data->native_window) {
+        SDL_free(data);
+        return SDL_SetError("Could not fetch native window");
+    }
+    
+    data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->native_window);
 
+    if (data->egl_surface == EGL_NO_SURFACE) {
+        SDL_free(data);
+        return SDL_SetError("Could not create GLES window surface");
+    }
+
+    window->driverdata = data;
+    Android_Window = window;
+    
     return 0;
 }
 
@@ -69,12 +91,23 @@ Android_SetWindowTitle(_THIS, SDL_Window * window)
 void
 Android_DestroyWindow(_THIS, SDL_Window * window)
 {
+    SDL_WindowData *data;
+    
     if (window == Android_Window) {
         Android_Window = NULL;
         if (Android_PauseSem) SDL_DestroySemaphore(Android_PauseSem);
         if (Android_ResumeSem) SDL_DestroySemaphore(Android_ResumeSem);
         Android_PauseSem = NULL;
         Android_ResumeSem = NULL;
+        
+        if(window->driverdata) {
+            data = (SDL_WindowData *) window->driverdata;
+            if(data->native_window) {
+                ANativeWindow_release(data->native_window);
+            }
+            SDL_free(window->driverdata);
+            window->driverdata = NULL;
+        }
     }
 }
 

+ 11 - 0
src/video/android/SDL_androidwindow.h

@@ -23,10 +23,21 @@
 #ifndef _SDL_androidwindow_h
 #define _SDL_androidwindow_h
 
+#include "../../core/android/SDL_android.h"
+#include "../SDL_egl.h"
+
 extern int Android_CreateWindow(_THIS, SDL_Window * window);
 extern void Android_SetWindowTitle(_THIS, SDL_Window * window);
 extern void Android_DestroyWindow(_THIS, SDL_Window * window);
 
+typedef struct
+{
+    EGLSurface egl_surface;
+    EGLContext egl_context; /* We use this to preserve the context when losing focus */
+    ANativeWindow* native_window;
+    
+} SDL_WindowData;
+
 #endif /* _SDL_androidwindow_h */
 
 /* vi: set ts=4 sw=4 expandtab: */

+ 37 - 19
src/video/x11/SDL_x11opengl.c

@@ -140,25 +140,6 @@ X11_GL_LoadLibrary(_THIS, const char *path)
         return SDL_SetError("OpenGL context already created");
     }
 
-    /* If SDL_GL_CONTEXT_EGL has been changed to 1, switch over to X11_GLES functions  */
-    if (_this->gl_config.use_egl == 1) {
-#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
-        _this->GL_LoadLibrary = X11_GLES_LoadLibrary;
-        _this->GL_GetProcAddress = X11_GLES_GetProcAddress;
-        _this->GL_UnloadLibrary = X11_GLES_UnloadLibrary;
-        _this->GL_CreateContext = X11_GLES_CreateContext;
-        _this->GL_MakeCurrent = X11_GLES_MakeCurrent;
-        _this->GL_SetSwapInterval = X11_GLES_SetSwapInterval;
-        _this->GL_GetSwapInterval = X11_GLES_GetSwapInterval;
-        _this->GL_SwapWindow = X11_GLES_SwapWindow;
-        _this->GL_DeleteContext = X11_GLES_DeleteContext;
-        return X11_GLES_LoadLibrary(_this, path);
-#else
-        return SDL_SetError("SDL not configured with OpenGL ES/EGL support");
-#endif
-    }
-
-
     /* Load the OpenGL library */
     if (path == NULL) {
         path = SDL_getenv("SDL_OPENGL_LIBRARY");
@@ -228,6 +209,38 @@ X11_GL_LoadLibrary(_THIS, const char *path)
 
     /* Initialize extensions */
     X11_GL_InitExtensions(_this);
+    
+    /* If SDL_GL_CONTEXT_EGL has been changed to 1, and there's 
+     * no GLX_EXT_create_context_es2_profile extension switch over to X11_GLES functions  */
+    if (_this->gl_config.use_egl == 1) {
+        if (_this->gl_data->HAS_GLX_EXT_create_context_es2_profile) {
+            /* We cheat a little bit here by using GLX instead of EGL 
+             * to improve our chances of getting hardware acceleration */
+            _this->gl_config.use_egl = 0;
+            _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
+        } else {
+#if SDL_VIDEO_OPENGL_EGL
+            X11_GL_UnloadLibrary(_this);
+            /* Better avoid conflicts! */
+            if (_this->gl_config.dll_handle != NULL ) {
+                GL_UnloadObject(_this->gl_config.dll_handle);
+                _this->gl_config.dll_handle = NULL;
+            }
+            _this->GL_LoadLibrary = X11_GLES_LoadLibrary;
+            _this->GL_GetProcAddress = X11_GLES_GetProcAddress;
+            _this->GL_UnloadLibrary = X11_GLES_UnloadLibrary;
+            _this->GL_CreateContext = X11_GLES_CreateContext;
+            _this->GL_MakeCurrent = X11_GLES_MakeCurrent;
+            _this->GL_SetSwapInterval = X11_GLES_SetSwapInterval;
+            _this->GL_GetSwapInterval = X11_GLES_GetSwapInterval;
+            _this->GL_SwapWindow = X11_GLES_SwapWindow;
+            _this->GL_DeleteContext = X11_GLES_DeleteContext;
+            return X11_GLES_LoadLibrary(_this, NULL);
+#else
+            return SDL_SetError("SDL not configured with EGL support");
+#endif
+        }
+    }
 
     return 0;
 }
@@ -369,6 +382,11 @@ X11_GL_InitExtensions(_THIS)
     if (HasExtension("GLX_EXT_visual_info", extensions)) {
         _this->gl_data->HAS_GLX_EXT_visual_info = SDL_TRUE;
     }
+    
+    /* Check for GLX_EXT_create_context_es2_profile */
+    if (HasExtension("GLX_EXT_create_context_es2_profile", extensions)) {
+        _this->gl_data->HAS_GLX_EXT_create_context_es2_profile = SDL_TRUE;
+    }
 
     if (context) {
         _this->gl_data->glXMakeCurrent(display, None, NULL);

+ 1 - 0
src/video/x11/SDL_x11opengl.h

@@ -34,6 +34,7 @@ struct SDL_GLDriverData
     SDL_bool HAS_GLX_EXT_visual_rating;
     SDL_bool HAS_GLX_EXT_visual_info;
     SDL_bool HAS_GLX_EXT_swap_control_tear;
+    SDL_bool HAS_GLX_EXT_create_context_es2_profile;
 
     Bool (*glXQueryExtension) (Display*,int*,int*);
     void *(*glXGetProcAddress) (const GLubyte*);

+ 28 - 360
src/video/x11/SDL_x11opengles.c

@@ -20,86 +20,22 @@
 */
 #include "SDL_config.h"
 
-#if SDL_VIDEO_DRIVER_X11 && SDL_VIDEO_OPENGL_ES
+#if SDL_VIDEO_DRIVER_X11 && SDL_VIDEO_OPENGL_EGL
 
 #include "SDL_x11video.h"
 #include "SDL_x11opengles.h"
 #include "SDL_x11opengl.h"
 
-#define DEFAULT_EGL "libEGL.so"
-#define DEFAULT_OGL_ES2 "libGLESv2.so"
-#define DEFAULT_OGL_ES_PVR "libGLES_CM.so"
-#define DEFAULT_OGL_ES "libGLESv1_CM.so"
-
-#define LOAD_FUNC(NAME) \
-    *((void**)&_this->gles_data->NAME) = dlsym(handle, #NAME); \
-    if (!_this->gles_data->NAME) \
-    { \
-        return SDL_SetError("Could not retrieve EGL function " #NAME); \
-    }
-
-/* GLES implementation of SDL OpenGL support */
-
-void *
-X11_GLES_GetProcAddress(_THIS, const char *proc)
-{
-    static char procname[1024];
-    void *handle;
-    void *retval;
-
-    handle = _this->gles_data->egl_dll_handle;
-    if (_this->gles_data->eglGetProcAddress) {
-        retval = _this->gles_data->eglGetProcAddress(proc);
-        if (retval) {
-            return retval;
-        }
-    }
-
-    handle = _this->gl_config.dll_handle;
-#if defined(__OpenBSD__) && !defined(__ELF__)
-#undef dlsym(x,y);
-#endif
-    retval = dlsym(handle, proc);
-    if (!retval && strlen(proc) <= 1022) {
-        procname[0] = '_';
-        strcpy(procname + 1, proc);
-        retval = dlsym(handle, procname);
-    }
-    return retval;
-}
-
-void
-X11_GLES_UnloadLibrary(_THIS)
-{
-    if ((_this->gles_data) && (_this->gl_config.driver_loaded)) {
-        _this->gles_data->eglTerminate(_this->gles_data->egl_display);
-
-        dlclose(_this->gl_config.dll_handle);
-        dlclose(_this->gles_data->egl_dll_handle);
-
-        SDL_free(_this->gles_data);
-        _this->gles_data = NULL;
-
-        _this->gl_config.dll_handle = NULL;
-        _this->gl_config.driver_loaded = 0;
-    }
-}
+/* EGL implementation of SDL OpenGL support */
 
 int
-X11_GLES_LoadLibrary(_THIS, const char *path)
-{
-    void *handle;
-    int dlopen_flags;
-
+X11_GLES_LoadLibrary(_THIS, const char *path) {
+        
     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
 
-    if (_this->gles_data) {
-        return SDL_SetError("OpenGL ES context already created");
-    }
-
     /* If SDL_GL_CONTEXT_EGL has been changed to 0, switch over to X11_GL functions  */
     if (_this->gl_config.use_egl == 0) {
-#if SDL_VIDEO_OPENGL_GLX
+        #if SDL_VIDEO_OPENGL_GLX
         _this->GL_LoadLibrary = X11_GL_LoadLibrary;
         _this->GL_GetProcAddress = X11_GL_GetProcAddress;
         _this->GL_UnloadLibrary = X11_GL_UnloadLibrary;
@@ -110,331 +46,63 @@ X11_GLES_LoadLibrary(_THIS, const char *path)
         _this->GL_SwapWindow = X11_GL_SwapWindow;
         _this->GL_DeleteContext = X11_GL_DeleteContext;
         return X11_GL_LoadLibrary(_this, path);
-#else
+        #else
         return SDL_SetError("SDL not configured with OpenGL/GLX support");
-#endif
+        #endif
     }
-
-#ifdef RTLD_GLOBAL
-    dlopen_flags = RTLD_LAZY | RTLD_GLOBAL;
-#else
-    dlopen_flags = RTLD_LAZY;
-#endif
-    handle = dlopen(path, dlopen_flags);
-    /* Catch the case where the application isn't linked with EGL */
-    if ((dlsym(handle, "eglChooseConfig") == NULL) && (path == NULL)) {
-
-        dlclose(handle);
-        path = getenv("SDL_VIDEO_EGL_DRIVER");
-        if (path == NULL) {
-            path = DEFAULT_EGL;
-        }
-        handle = dlopen(path, dlopen_flags);
-    }
-
-    if (handle == NULL) {
-        return SDL_SetError("Could not load OpenGL ES/EGL library");
-    }
-
-    /* Unload the old driver and reset the pointers */
-    X11_GLES_UnloadLibrary(_this);
-
-    _this->gles_data = (struct SDL_PrivateGLESData *) SDL_calloc(1, sizeof(SDL_PrivateGLESData));
-    if (!_this->gles_data) {
-        return SDL_OutOfMemory();
-    }
-
-    /* Load new function pointers */
-    LOAD_FUNC(eglGetDisplay);
-    LOAD_FUNC(eglInitialize);
-    LOAD_FUNC(eglTerminate);
-    LOAD_FUNC(eglGetProcAddress);
-    LOAD_FUNC(eglChooseConfig);
-    LOAD_FUNC(eglGetConfigAttrib);
-    LOAD_FUNC(eglCreateContext);
-    LOAD_FUNC(eglDestroyContext);
-    LOAD_FUNC(eglCreateWindowSurface);
-    LOAD_FUNC(eglDestroySurface);
-    LOAD_FUNC(eglMakeCurrent);
-    LOAD_FUNC(eglSwapBuffers);
-    LOAD_FUNC(eglSwapInterval);
-
-    _this->gles_data->egl_display =
-        _this->gles_data->eglGetDisplay((NativeDisplayType) data->display);
-
-    if (!_this->gles_data->egl_display) {
-        return SDL_SetError("Could not get EGL display");
-    }
-
-    if (_this->gles_data->
-        eglInitialize(_this->gles_data->egl_display, NULL,
-                      NULL) != EGL_TRUE) {
-        return SDL_SetError("Could not initialize EGL");
-    }
-
-    _this->gles_data->egl_dll_handle = handle;
-
-    path = getenv("SDL_VIDEO_GL_DRIVER");
-    handle = dlopen(path, dlopen_flags);
-    if ((path == NULL) | (handle == NULL)) {
-        if (_this->gl_config.major_version > 1) {
-            path = DEFAULT_OGL_ES2;
-            handle = dlopen(path, dlopen_flags);
-        } else {
-            path = DEFAULT_OGL_ES;
-            handle = dlopen(path, dlopen_flags);
-            if (handle == NULL) {
-                path = DEFAULT_OGL_ES_PVR;
-                handle = dlopen(path, dlopen_flags);
-            }
-        }
-    }
-
-    if (handle == NULL) {
-        return SDL_SetError("Could not initialize OpenGL ES library");
-    }
-
-    _this->gl_config.dll_handle = handle;
-    _this->gl_config.driver_loaded = 1;
-
-    if (path) {
-        strncpy(_this->gl_config.driver_path, path,
-                sizeof(_this->gl_config.driver_path) - 1);
-    } else {
-        strcpy(_this->gl_config.driver_path, "");
-    }
-    return 0;
+    
+    return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) data->display);
 }
 
 XVisualInfo *
 X11_GLES_GetVisual(_THIS, Display * display, int screen)
 {
-    /* 64 seems nice. */
-    EGLint attribs[64];
-    EGLint found_configs = 0;
+   
+    XVisualInfo *egl_visualinfo = NULL;
     EGLint visual_id;
-    int i;
+    XVisualInfo vi_in;
+    int out_count;
 
-    if (!_this->gles_data) {
+    if (!_this->egl_data) {
         /* The EGL library wasn't loaded, SDL_GetError() should have info */
         return NULL;
     }
 
-    i = 0;
-    attribs[i++] = EGL_RED_SIZE;
-    attribs[i++] = _this->gl_config.red_size;
-    attribs[i++] = EGL_GREEN_SIZE;
-    attribs[i++] = _this->gl_config.green_size;
-    attribs[i++] = EGL_BLUE_SIZE;
-    attribs[i++] = _this->gl_config.blue_size;
-
-    if (_this->gl_config.alpha_size) {
-        attribs[i++] = EGL_ALPHA_SIZE;
-        attribs[i++] = _this->gl_config.alpha_size;
-    }
-
-    if (_this->gl_config.buffer_size) {
-        attribs[i++] = EGL_BUFFER_SIZE;
-        attribs[i++] = _this->gl_config.buffer_size;
-    }
-
-    attribs[i++] = EGL_DEPTH_SIZE;
-    attribs[i++] = _this->gl_config.depth_size;
-
-    if (_this->gl_config.stencil_size) {
-        attribs[i++] = EGL_STENCIL_SIZE;
-        attribs[i++] = _this->gl_config.stencil_size;
-    }
-
-    if (_this->gl_config.multisamplebuffers) {
-        attribs[i++] = EGL_SAMPLE_BUFFERS;
-        attribs[i++] = _this->gl_config.multisamplebuffers;
-    }
-
-    if (_this->gl_config.multisamplesamples) {
-        attribs[i++] = EGL_SAMPLES;
-        attribs[i++] = _this->gl_config.multisamplesamples;
-    }
-
-    attribs[i++] = EGL_RENDERABLE_TYPE;
-    if (_this->gl_config.major_version == 2) {
-        attribs[i++] = EGL_OPENGL_ES2_BIT;
-    } else {
-        attribs[i++] = EGL_OPENGL_ES_BIT;
-    }
-
-    attribs[i++] = EGL_NONE;
-
-    if (_this->gles_data->eglChooseConfig(_this->gles_data->egl_display,
-                                          attribs,
-                                          &_this->gles_data->egl_config, 1,
-                                          &found_configs) == EGL_FALSE ||
-        found_configs == 0) {
-        SDL_SetError("Couldn't find matching EGL config");
-        return NULL;
-    }
-
-    if (_this->gles_data->eglGetConfigAttrib(_this->gles_data->egl_display,
-                                             _this->gles_data->egl_config,
-                                             EGL_NATIVE_VISUAL_ID,
-                                             &visual_id) ==
-        EGL_FALSE || !visual_id) {
+    if (_this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display,
+                                            _this->egl_data->egl_config,
+                                            EGL_NATIVE_VISUAL_ID,
+                                            &visual_id) == EGL_FALSE || !visual_id) {
         /* Use the default visual when all else fails */
-        XVisualInfo vi_in;
-        int out_count;
         vi_in.screen = screen;
-
-        _this->gles_data->egl_visualinfo = XGetVisualInfo(display,
-                                                          VisualScreenMask,
-                                                          &vi_in, &out_count);
+        egl_visualinfo = XGetVisualInfo(display,
+                                        VisualScreenMask,
+                                        &vi_in, &out_count);
     } else {
-        XVisualInfo vi_in;
-        int out_count;
-
         vi_in.screen = screen;
         vi_in.visualid = visual_id;
-        _this->gles_data->egl_visualinfo = XGetVisualInfo(display,
-                                                          VisualScreenMask |
-                                                          VisualIDMask,
-                                                          &vi_in, &out_count);
+        egl_visualinfo = XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &vi_in, &out_count);
     }
 
-    return _this->gles_data->egl_visualinfo;
+    return egl_visualinfo;
 }
 
 SDL_GLContext
 X11_GLES_CreateContext(_THIS, SDL_Window * window)
 {
-    EGLint context_attrib_list[] = {
-        EGL_CONTEXT_CLIENT_VERSION,
-        1,
-        EGL_NONE
-    };
-
+    SDL_GLContext context;
     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
     Display *display = data->videodata->display;
-    SDL_GLContext context = (SDL_GLContext)1;
 
     XSync(display, False);
-
-    if (_this->gl_config.major_version) {
-        context_attrib_list[1] = _this->gl_config.major_version;
-    }
-
-    _this->gles_data->egl_context =
-        _this->gles_data->eglCreateContext(_this->gles_data->egl_display,
-                                           _this->gles_data->egl_config,
-                                           EGL_NO_CONTEXT, context_attrib_list);
+    context = SDL_EGL_CreateContext(_this, data->egl_surface);
     XSync(display, False);
 
-    if (_this->gles_data->egl_context == EGL_NO_CONTEXT) {
-        SDL_SetError("Could not create EGL context");
-        return NULL;
-    }
-
-    _this->gles_data->egl_swapinterval = 0;
-
-    if (X11_GLES_MakeCurrent(_this, window, context) < 0) {
-        X11_GLES_DeleteContext(_this, context);
-        return NULL;
-    }
-
     return context;
 }
 
-int
-X11_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
-{
-/*
-    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
-    Display *display = data->videodata->display;
-*/
-
-    if (!_this->gles_data) {
-        return SDL_SetError("OpenGL not initialized");
-    }
-
-    if (!_this->gles_data->eglMakeCurrent(_this->gles_data->egl_display,
-                                          _this->gles_data->egl_surface,
-                                          _this->gles_data->egl_surface,
-                                          _this->gles_data->egl_context)) {
-        return SDL_SetError("Unable to make EGL context current");
-    }
-
-/*
-    XSync(display, False);
-*/
-
-    return 1;
-}
-
-int
-X11_GLES_SetSwapInterval(_THIS, int interval)
-{
-    if (_this->gles_data) {
-        return SDL_SetError("OpenGL ES context not active");
-    }
-
-    EGLBoolean status;
-    status = _this->gles_data->eglSwapInterval(_this->gles_data->egl_display, interval);
-    if (status == EGL_TRUE) {
-        _this->gles_data->egl_swapinterval = interval;
-        return 0;
-    }
-
-    return SDL_SetError("Unable to set the EGL swap interval");
-}
-
-int
-X11_GLES_GetSwapInterval(_THIS)
-{
-    if (_this->gles_data) {
-        return SDL_SetError("OpenGL ES context not active");
-    }
-
-    return _this->gles_data->egl_swapinterval;
-}
-
-void
-X11_GLES_SwapWindow(_THIS, SDL_Window * window)
-{
-    _this->gles_data->eglSwapBuffers(_this->gles_data->egl_display,
-                                     _this->gles_data->egl_surface);
-}
-
-void
-X11_GLES_DeleteContext(_THIS, SDL_GLContext context)
-{
-    /* Clean up GLES and EGL */
-    if (!_this->gles_data) {
-        return;
-    }
-
-    if (_this->gles_data->egl_context != EGL_NO_CONTEXT ||
-        _this->gles_data->egl_surface != EGL_NO_SURFACE) {
-        _this->gles_data->eglMakeCurrent(_this->gles_data->egl_display,
-                                         EGL_NO_SURFACE, EGL_NO_SURFACE,
-                                         EGL_NO_CONTEXT);
-
-        if (_this->gles_data->egl_context != EGL_NO_CONTEXT) {
-            _this->gles_data->eglDestroyContext(_this->gles_data->egl_display,
-                                                _this->gles_data->
-                                                egl_context);
-            _this->gles_data->egl_context = EGL_NO_CONTEXT;
-        }
-
-        if (_this->gles_data->egl_surface != EGL_NO_SURFACE) {
-            _this->gles_data->eglDestroySurface(_this->gles_data->egl_display,
-                                                _this->gles_data->
-                                                egl_surface);
-            _this->gles_data->egl_surface = EGL_NO_SURFACE;
-        }
-    }
-
-    /* crappy fix */
-    X11_GLES_UnloadLibrary(_this);
-}
+SDL_EGL_SwapWindow_impl(X11)
+SDL_EGL_MakeCurrent_impl(X11)
 
-#endif /* SDL_VIDEO_DRIVER_X11 && SDL_VIDEO_OPENGL_ES */
+#endif /* SDL_VIDEO_DRIVER_X11 && SDL_VIDEO_OPENGL_EGL */
 
 /* vi: set ts=4 sw=4 expandtab: */

+ 13 - 64
src/video/x11/SDL_x11opengles.h

@@ -23,81 +23,30 @@
 #ifndef _SDL_x11opengles_h
 #define _SDL_x11opengles_h
 
-#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
-#include <GLES/gl.h>
-#include <GLES/egl.h>
-#include <dlfcn.h>
-#if defined(__OpenBSD__) && !defined(__ELF__)
-#define dlsym(x,y) dlsym(x, "_" y)
-#endif
+#if SDL_VIDEO_OPENGL_EGL
 
 #include "../SDL_sysvideo.h"
+#include "../SDL_egl.h"
 
 typedef struct SDL_PrivateGLESData
 {
-    XVisualInfo *egl_visualinfo;
-    void *egl_dll_handle;
-    EGLDisplay egl_display;
-    EGLContext egl_context;     /* Current GLES context */
-    EGLSurface egl_surface;
-    EGLConfig egl_config;
-    int egl_swapinterval;
-
-      EGLDisplay(*eglGetDisplay) (NativeDisplayType display);
-      EGLBoolean(*eglInitialize) (EGLDisplay dpy, EGLint * major,
-                                  EGLint * minor);
-      EGLBoolean(*eglTerminate) (EGLDisplay dpy);
-
-    void *(*eglGetProcAddress) (const char * procName);
-
-      EGLBoolean(*eglChooseConfig) (EGLDisplay dpy,
-                                    const EGLint * attrib_list,
-                                    EGLConfig * configs,
-                                    EGLint config_size, EGLint * num_config);
-
-      EGLContext(*eglCreateContext) (EGLDisplay dpy,
-                                     EGLConfig config,
-                                     EGLContext share_list,
-                                     const EGLint * attrib_list);
-
-      EGLBoolean(*eglDestroyContext) (EGLDisplay dpy, EGLContext ctx);
-
-      EGLSurface(*eglCreateWindowSurface) (EGLDisplay dpy,
-                                           EGLConfig config,
-                                           NativeWindowType window,
-                                           const EGLint * attrib_list);
-      EGLBoolean(*eglDestroySurface) (EGLDisplay dpy, EGLSurface surface);
-
-      EGLBoolean(*eglMakeCurrent) (EGLDisplay dpy, EGLSurface draw,
-                                   EGLSurface read, EGLContext ctx);
-
-      EGLBoolean(*eglSwapBuffers) (EGLDisplay dpy, EGLSurface draw);
-
-      EGLBoolean(*eglSwapInterval) (EGLDisplay dpy, EGLint interval);
-
-    const char *(*eglQueryString) (EGLDisplay dpy, EGLint name);
-
-      EGLBoolean(*eglGetConfigAttrib) (EGLDisplay dpy, EGLConfig config,
-                                       EGLint attribute, EGLint * value);
-
 } SDL_PrivateGLESData;
 
 /* OpenGLES functions */
-extern SDL_GLContext X11_GLES_CreateContext(_THIS, SDL_Window * window);
-extern XVisualInfo *X11_GLES_GetVisual(_THIS, Display * display, int screen);
-extern int X11_GLES_MakeCurrent(_THIS, SDL_Window * window,
-                                SDL_GLContext context);
-extern int X11_GLES_GetAttribute(_THIS, SDL_GLattr attrib, int *value);
-extern int X11_GLES_LoadLibrary(_THIS, const char *path);
-extern void *X11_GLES_GetProcAddress(_THIS, const char *proc);
-extern void X11_GLES_UnloadLibrary(_THIS);
+#define X11_GLES_GetAttribute SDL_EGL_GetAttribute
+#define X11_GLES_GetProcAddress SDL_EGL_GetProcAddress
+#define X11_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
+#define X11_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
+#define X11_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
+#define X11_GLES_DeleteContext SDL_EGL_DeleteContext
 
-extern int X11_GLES_SetSwapInterval(_THIS, int interval);
-extern int X11_GLES_GetSwapInterval(_THIS);
+extern int X11_GLES_LoadLibrary(_THIS, const char *path);
+extern XVisualInfo *X11_GLES_GetVisual(_THIS, Display * display, int screen);
+extern SDL_GLContext X11_GLES_CreateContext(_THIS, SDL_Window * window);
 extern void X11_GLES_SwapWindow(_THIS, SDL_Window * window);
-extern void X11_GLES_DeleteContext(_THIS, SDL_GLContext context);
+extern int X11_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
 
-#endif /* SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2 */
+#endif /* SDL_VIDEO_OPENGL_EGL */
 
 #endif /* _SDL_x11opengles_h */
 

+ 2 - 2
src/video/x11/SDL_x11video.c

@@ -35,7 +35,7 @@
 #include "SDL_x11touch.h"
 #include "SDL_x11xinput2.h"
 
-#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_OPENGL_EGL
 #include "SDL_x11opengles.h"
 #endif
 
@@ -394,7 +394,7 @@ X11_CreateDevice(int devindex)
     device->GL_GetSwapInterval = X11_GL_GetSwapInterval;
     device->GL_SwapWindow = X11_GL_SwapWindow;
     device->GL_DeleteContext = X11_GL_DeleteContext;
-#elif SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
+#elif SDL_VIDEO_OPENGL_EGL
     device->GL_LoadLibrary = X11_GLES_LoadLibrary;
     device->GL_GetProcAddress = X11_GLES_GetProcAddress;
     device->GL_UnloadLibrary = X11_GLES_UnloadLibrary;

+ 21 - 23
src/video/x11/SDL_x11window.c

@@ -34,7 +34,7 @@
 #include "SDL_x11shape.h"
 #include "SDL_x11xinput2.h"
 
-#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_OPENGL_EGL
 #include "SDL_x11opengles.h"
 #endif
 
@@ -363,11 +363,11 @@ X11_CreateWindow(_THIS, SDL_Window * window)
     Atom XdndAware, xdnd_version = 5;
     Uint32 fevent = 0;
 
-#if SDL_VIDEO_OPENGL_GLX || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_OPENGL_GLX || SDL_VIDEO_OPENGL_EGL
     if (window->flags & SDL_WINDOW_OPENGL) {
         XVisualInfo *vinfo;
 
-#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
+#if SDL_VIDEO_OPENGL_EGL
         if (_this->gl_config.use_egl == 1) {
             vinfo = X11_GLES_GetVisual(_this, display, screen);
         } else
@@ -481,26 +481,6 @@ X11_CreateWindow(_THIS, SDL_Window * window)
     if (!w) {
         return SDL_SetError("Couldn't create window");
     }
-#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
-    if ((window->flags & SDL_WINDOW_OPENGL) && (_this->gl_config.use_egl == 1)) {
-        if (!_this->gles_data) {
-            XDestroyWindow(display, w);
-            return -1;
-        }
-
-        /* Create the GLES window surface */
-        _this->gles_data->egl_surface =
-            _this->gles_data->eglCreateWindowSurface(_this->gles_data->
-                                                 egl_display,
-                                                 _this->gles_data->egl_config,
-                                                 (NativeWindowType) w, NULL);
-
-        if (_this->gles_data->egl_surface == EGL_NO_SURFACE) {
-            XDestroyWindow(display, w);
-            return SDL_SetError("Could not create GLES window surface");
-        }
-    }
-#endif
 
     SetWindowBordered(display, screen, w,
                       (window->flags & SDL_WINDOW_BORDERLESS) == 0);
@@ -568,6 +548,24 @@ X11_CreateWindow(_THIS, SDL_Window * window)
         return -1;
     }
 
+#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
+    if ((window->flags & SDL_WINDOW_OPENGL) && (_this->gl_config.use_egl == 1)) {
+        if (!_this->egl_data) {
+            XDestroyWindow(display, w);
+            return -1;
+        }
+
+        /* Create the GLES window surface */
+        ((SDL_WindowData *) window->driverdata)->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) w);
+
+        if (((SDL_WindowData *) window->driverdata)->egl_surface == EGL_NO_SURFACE) {
+            XDestroyWindow(display, w);
+            return SDL_SetError("Could not create GLES window surface");
+        }
+    }
+#endif
+    
+
 #ifdef X_HAVE_UTF8_STRING
     if (SDL_X11_HAVE_UTF8) {
         pXGetICValues(((SDL_WindowData *) window->driverdata)->ic,

+ 7 - 0
src/video/x11/SDL_x11window.h

@@ -30,6 +30,10 @@
 #define PENDING_FOCUS_IN_TIME   200
 #define PENDING_FOCUS_OUT_TIME  200
 
+#if SDL_VIDEO_OPENGL_EGL   
+#include <EGL/egl.h>
+#endif
+
 typedef enum
 {
     PENDING_FOCUS_NONE,
@@ -59,6 +63,9 @@ typedef struct
     struct SDL_VideoData *videodata;
     Atom xdnd_req;
     Window xdnd_source;
+#if SDL_VIDEO_OPENGL_EGL  
+    EGLSurface egl_surface;
+#endif
 } SDL_WindowData;
 
 extern void X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags);