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

This commit is contained in:
Gabriel Jacobo
2013-08-19 16:29:46 -03:00
parent b44267693d
commit 0eeb76d869
25 changed files with 927 additions and 878 deletions

View File

@@ -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

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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;
}
}
}

View File

@@ -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: */