mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-03-27 10:51:54 +00:00
Fixes bug #2037, common EGL code for Android and X11
This commit is contained in:
@@ -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: */
|
||||
|
||||
Reference in New Issue
Block a user