Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,516 changes: 1,188 additions & 328 deletions src/core/android/SDL_android.c

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions src/core/android/SDL_android.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ typedef enum
void Android_SendLifecycleEvent(SDL_AndroidLifecycleEvent event);
bool Android_WaitLifecycleEvent(SDL_AndroidLifecycleEvent *event, Sint64 timeoutNS);

void Android_LockActivityMutex(void);
void Android_UnlockActivityMutex(void);
void Android_LockActivityState(void);
void Android_UnlockActivityState(void);

void Android_SetAllowRecreateActivity(bool enabled);

Expand Down Expand Up @@ -157,6 +157,10 @@ bool Android_JNI_OpenFileDialog(SDL_DialogFileCallback callback, void *userdata,
const SDL_DialogFileFilter *filters, int nfilters, bool forwrite,
bool multiple);

// Pump RPC commands
void Android_PumpRPC(SDL_Window *window);


// Ends C function definitions when using C++
#ifdef __cplusplus
/* *INDENT-OFF* */
Expand Down
17 changes: 15 additions & 2 deletions src/events/SDL_events.c
Original file line number Diff line number Diff line change
Expand Up @@ -1513,7 +1513,13 @@ static void SDL_PumpEventsInternal(bool push_sentinel)

#ifdef SDL_PLATFORM_ANDROID
// Android event processing is independent of the video subsystem
Android_PumpEvents(0);
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (_this) {
SDL_Window *window = _this->windows;
if (window) {
Android_PumpEvents(window, 0);
}
}
Comment on lines +1517 to +1522

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still need to pump events for lifecycle activity even if there's no window or video hasn't been initialized.

#else
// Get events from the video subsystem
SDL_VideoDevice *_this = SDL_GetVideoDevice();
Expand Down Expand Up @@ -1746,7 +1752,14 @@ bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS)
}
delay = (expiration - now);
}
Android_PumpEvents(delay);

SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (_this) {
SDL_Window *window = _this->windows;
if (window) {
Android_PumpEvents(window, delay);
}
}
}
#else
SDL_VideoDevice *_this = SDL_GetVideoDevice();
Expand Down
6 changes: 3 additions & 3 deletions src/joystick/android/SDL_sysjoystick.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ static int numjoysticks = 0;
* This code manipulation is done to get a sequential list of codes.
* FIXME: This is only suited for the case where we use a fixed number of buttons determined by ANDROID_MAX_NBUTTONS
*/
static int keycode_to_SDL(int keycode)
int Android_keycode_to_SDL(int keycode)
{
// FIXME: If this function gets too unwieldy in the future, replace with a lookup table
int button = 0;
Expand Down Expand Up @@ -198,7 +198,7 @@ bool Android_OnPadDown(int device_id, int keycode)
{
Uint64 timestamp = SDL_GetTicksNS();
SDL_joylist_item *item;
int button = keycode_to_SDL(keycode);
int button = Android_keycode_to_SDL(keycode);
if (button >= 0) {
SDL_LockJoysticks();
item = JoystickByDeviceId(device_id);
Expand All @@ -218,7 +218,7 @@ bool Android_OnPadUp(int device_id, int keycode)
{
Uint64 timestamp = SDL_GetTicksNS();
SDL_joylist_item *item;
int button = keycode_to_SDL(keycode);
int button = Android_keycode_to_SDL(keycode);
if (button >= 0) {
SDL_LockJoysticks();
item = JoystickByDeviceId(device_id);
Expand Down
1 change: 1 addition & 0 deletions src/joystick/android/SDL_sysjoystick_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include "../SDL_sysjoystick.h"

extern int Android_keycode_to_SDL(int keycode);
extern bool Android_OnPadDown(int device_id, int keycode);
extern bool Android_OnPadUp(int device_id, int keycode);
extern bool Android_OnJoy(int device_id, int axisnum, float value);
Expand Down
6 changes: 3 additions & 3 deletions src/render/SDL_render.c
Original file line number Diff line number Diff line change
Expand Up @@ -1069,7 +1069,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
}

#ifdef SDL_PLATFORM_ANDROID
if (!Android_WaitActiveAndLockActivity()) {
if (!Android_WaitActiveAndLockActivity(window)) {
return NULL;
}
#endif
Expand Down Expand Up @@ -1249,7 +1249,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
SDL_renderers = renderer;

#ifdef SDL_PLATFORM_ANDROID
Android_UnlockActivityMutex();
Android_UnlockActivityState();
#endif

SDL_ClearError();
Expand All @@ -1258,7 +1258,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)

error:
#ifdef SDL_PLATFORM_ANDROID
Android_UnlockActivityMutex();
Android_UnlockActivityState();
#endif

if (renderer) {
Expand Down
125 changes: 72 additions & 53 deletions src/video/android/SDL_androidevents.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,43 +35,40 @@
#ifdef SDL_VIDEO_OPENGL_EGL
static void android_egl_context_restore(SDL_Window *window)
{
if (window) {
SDL_WindowData *data = window->internal;
SDL_GL_MakeCurrent(window, NULL);
if (!SDL_GL_MakeCurrent(window, (SDL_GLContext)data->egl_context)) {
// The context is no longer valid, create a new one
data->egl_context = (EGLContext)SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, (SDL_GLContext)data->egl_context);
SDL_Event event;
SDL_zero(event);
event.type = SDL_EVENT_RENDER_DEVICE_RESET;
event.render.windowID = SDL_GetWindowID(window);
SDL_PushEvent(&event);
}
data->backup_done = false;

SDL_GL_SetSwapInterval(data->swap_interval);
SDL_WindowData *data = window->internal;
SDL_GL_MakeCurrent(window, NULL);
if (!SDL_GL_MakeCurrent(window, (SDL_GLContext)data->egl_context)) {
// The context is no longer valid, create a new one
data->egl_context = (EGLContext)SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, (SDL_GLContext)data->egl_context);
SDL_Event event;
SDL_zero(event);
event.type = SDL_EVENT_RENDER_DEVICE_RESET;
event.render.windowID = SDL_GetWindowID(window);
SDL_PushEvent(&event);
}
data->backup_done = false;

SDL_GL_SetSwapInterval(data->swap_interval);
}

static void android_egl_context_backup(SDL_Window *window)
{
if (window) {
int interval = 0;
// Keep a copy of the EGL Context so we can try to restore it when we resume
SDL_WindowData *data = window->internal;
data->egl_context = SDL_GL_GetCurrentContext();

// Save/Restore the swap interval / vsync
if (SDL_GL_GetSwapInterval(&interval)) {
data->has_swap_interval = 1;
data->swap_interval = interval;
}

// We need to do this so the EGLSurface can be freed
SDL_GL_MakeCurrent(window, NULL);
data->backup_done = true;
int interval = 0;
// Keep a copy of the EGL Context so we can try to restore it when we resume
SDL_WindowData *data = window->internal;
data->egl_context = SDL_GL_GetCurrentContext();

SDL_Log("android_egl_context_backup ...");
// Save/Restore the swap interval / vsync
if (SDL_GL_GetSwapInterval(&interval)) {
data->has_swap_interval = 1;
data->swap_interval = interval;
}

// We need to do this so the EGLSurface can be freed
SDL_GL_MakeCurrent(window, NULL);
data->backup_done = true;
}
#endif

Expand Down Expand Up @@ -110,7 +107,7 @@ static void Android_ResumeAudio(void)
}
}

static void Android_OnPause(void)
static void Android_OnPause(SDL_Window *window)
{
SDL_OnApplicationWillEnterBackground();
SDL_OnApplicationDidEnterBackground();
Expand All @@ -121,10 +118,8 @@ static void Android_OnPause(void)
* was being queued.
*/
#ifdef SDL_VIDEO_OPENGL_EGL
if (Android_Window && !Android_Window->external_graphics_context) {
Android_LockActivityMutex();
android_egl_context_backup(Android_Window);
Android_UnlockActivityMutex();
if (window && !window->external_graphics_context) {
android_egl_context_backup(window);
}
#endif

Expand All @@ -136,7 +131,7 @@ static void Android_OnPause(void)
Android_Paused = true;
}

static void Android_OnResume(void)
static void Android_OnResume(SDL_Window *window)
{
Android_Paused = false;

Expand All @@ -146,10 +141,8 @@ static void Android_OnResume(void)

#ifdef SDL_VIDEO_OPENGL_EGL
// Restore the GL Context from here, as this operation is thread dependent
if (Android_Window && !Android_Window->external_graphics_context && !SDL_HasEvent(SDL_EVENT_QUIT)) {
Android_LockActivityMutex();
android_egl_context_restore(Android_Window);
Android_UnlockActivityMutex();
if (window && !window->external_graphics_context && !SDL_HasEvent(SDL_EVENT_QUIT)) {
android_egl_context_restore(window);
}
#endif

Expand All @@ -176,17 +169,17 @@ static void Android_OnDestroy(void)
Android_Destroyed = true;
}

static void Android_HandleLifecycleEvent(SDL_AndroidLifecycleEvent event)
static void Android_HandleLifecycleEvent(SDL_Window *window, SDL_AndroidLifecycleEvent event)
{
switch (event) {
case SDL_ANDROID_LIFECYCLE_WAKE:
// Nothing to do, just return
break;
case SDL_ANDROID_LIFECYCLE_PAUSE:
Android_OnPause();
Android_OnPause(window);
break;
case SDL_ANDROID_LIFECYCLE_RESUME:
Android_OnResume();
Android_OnResume(window);
break;
case SDL_ANDROID_LIFECYCLE_LOWMEMORY:
Android_OnLowMemory();
Expand All @@ -211,14 +204,17 @@ static Sint64 GetLifecycleEventTimeout(bool paused, Sint64 timeoutNS)
return timeoutNS;
}

void Android_PumpEvents(Sint64 timeoutNS)
void Android_PumpEvents(SDL_Window *window, Sint64 timeoutNS)
{
SDL_AndroidLifecycleEvent event;
bool paused = Android_Paused;

while (!Android_Destroyed &&
Android_WaitLifecycleEvent(&event, GetLifecycleEventTimeout(paused, timeoutNS))) {
Android_HandleLifecycleEvent(event);

Android_PumpRPC(window);

Android_HandleLifecycleEvent(window, event);

switch (event) {
case SDL_ANDROID_LIFECYCLE_WAKE:
Expand All @@ -238,24 +234,47 @@ void Android_PumpEvents(Sint64 timeoutNS)
}
}

bool Android_WaitActiveAndLockActivity(void)

void Android_PumpLifecycleEvents(SDL_Window *window)
{
/* Make sure we have pumped all events so that Android_Paused state is correct */
// Make sure we have pumped all events so that Android_Paused state is correct
SDL_AndroidLifecycleEvent event;
while (!Android_Destroyed && Android_WaitLifecycleEvent(&event, 0)) {
Android_HandleLifecycleEvent(event);
Android_HandleLifecycleEvent(window, event);
}
}

while (Android_Paused && !Android_Destroyed) {
Android_PumpEvents(-1);
}
bool Android_WaitActiveAndLockActivity(SDL_Window *window)
{
retry:

// Lock first.
// So no new lifecycle event comes in the meantimes from the SDLActivity,
// Hence SDLActivity won't change state.
Android_LockActivityState();

// Make sure we have pumped all events so that Android_Paused state is correct
Android_PumpLifecycleEvents(window);

if (Android_Destroyed) {
SDL_SetError("Android activity has been destroyed");
Android_UnlockActivityState();
return false;
}

Android_LockActivityMutex();
if (!Android_Paused) {
// SDLActivity is Active. return lock'ed
Android_PumpRPC(window);
return true;
} else {
// Still Paused
// Unlock and wait for the SDLActivity to send new cycle events
// or for the user to move the app to foreground.
Android_UnlockActivityState();
SDL_Delay(10);
goto retry;
}

return true;
}

Expand Down
5 changes: 3 additions & 2 deletions src/video/android/SDL_androidevents.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "SDL_internal.h"

extern void Android_InitEvents(void);
extern void Android_PumpEvents(Sint64 timeoutNS);
extern bool Android_WaitActiveAndLockActivity(void);
extern void Android_PumpEvents(SDL_Window *window, Sint64 timeoutNS);
extern bool Android_WaitActiveAndLockActivity(SDL_Window *window);
extern void Android_QuitEvents(void);
extern void Android_PumpLifecycleEvents(SDL_Window *window);
8 changes: 2 additions & 6 deletions src/video/android/SDL_androidgl.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ SDL_GLContext Android_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *win
{
SDL_GLContext result;

if (!Android_WaitActiveAndLockActivity()) {
if (!Android_WaitActiveAndLockActivity(window)) {
return NULL;
}

result = SDL_EGL_CreateContext(_this, window->internal->egl_surface);

Android_UnlockActivityMutex();
Android_UnlockActivityState();

return result;
}
Expand All @@ -64,8 +64,6 @@ bool Android_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
bool result;

Android_LockActivityMutex();

/* The following two calls existed in the original Java code
* If you happen to have a device that's affected by their removal,
* please report to our bug tracker. -- Gabriel
Expand All @@ -75,8 +73,6 @@ bool Android_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window)
_this->egl_data->eglWaitGL();*/
result = SDL_EGL_SwapBuffers(_this, window->internal->egl_surface);

Android_UnlockActivityMutex();

return result;
}

Expand Down
6 changes: 3 additions & 3 deletions src/video/android/SDL_androidvideo.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,15 +300,15 @@ void Android_SendResize(SDL_Window *window)
}
}

void Android_SetWindowSafeAreaInsets(int left, int right, int top, int bottom)
void Android_SetWindowSafeAreaInsets(SDL_Window *window, int left, int right, int top, int bottom)
{
Android_SafeInsetLeft = left;
Android_SafeInsetRight = right;
Android_SafeInsetTop = top;
Android_SafeInsetBottom = bottom;

if (Android_Window) {
SDL_SetWindowSafeAreaInsets(Android_Window, left, right, top, bottom);
if (window) {
SDL_SetWindowSafeAreaInsets(window, left, right, top, bottom);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/video/android/SDL_androidvideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ extern void Android_SetScreenResolution(int surfaceWidth, int surfaceHeight, int
extern void Android_SetFormat(int format_wanted, int format_got);
extern void Android_SetOrientation(SDL_DisplayOrientation orientation);
extern void Android_SendResize(SDL_Window *window);
extern void Android_SetWindowSafeAreaInsets(int left, int right, int top, int bottom);
extern void Android_SetWindowSafeAreaInsets(SDL_Window *window, int left, int right, int top, int bottom);
extern void Android_SetDarkMode(bool enabled);

// Private display data
Expand Down
Loading
Loading