mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-10-15 22:35:59 +00:00
Fixes bug #2037, common EGL code for Android and X11
This commit is contained in:
@@ -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);
|
||||
|
407
src/video/SDL_egl.c
Normal file
407
src/video/SDL_egl.c
Normal file
@@ -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
src/video/SDL_egl.h
Normal file
132
src/video/SDL_egl.h
Normal file
@@ -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);
|
||||
|
Reference in New Issue
Block a user