Fixes bug #2037, common EGL code for Android and X11
parent
b44267693d
commit
0eeb76d869
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
69
configure.in
69
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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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: */
|
||||
|
|
@ -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: */
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
Android_GLES_SwapWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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: */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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;
|
||||
*/
|
||||
SDL_EGL_SwapWindow_impl(X11)
|
||||
SDL_EGL_MakeCurrent_impl(X11)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#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: */
|
||||
|
|
|
@ -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);
|
||||
#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_LoadLibrary(_THIS, const char *path);
|
||||
extern void *X11_GLES_GetProcAddress(_THIS, const char *proc);
|
||||
extern void X11_GLES_UnloadLibrary(_THIS);
|
||||
|
||||
extern int X11_GLES_SetSwapInterval(_THIS, int interval);
|
||||
extern int X11_GLES_GetSwapInterval(_THIS);
|
||||
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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue