src/video/android/SDL_androidwindow.c
author Sylvain Becker <sylvain.becker@gmail.com>
Wed, 09 Jan 2019 15:18:41 +0100
changeset 12512 afc8e5d1d992
parent 12503 806492103856
child 12514 8034efde00c5
permissions -rw-r--r--
Android: concurrency issue for Android_SetWindowFullscreen()

It accesses data->native_window, which can be changed by onNativeSurfacedChanged().

Currently, Android_SetWindowFullscreen() may access data->native_window after it
has been released, and before a new reference is acquired.

(can be reproduced by adding some SDL_Delay() in onNativeSurfacedChanged and
Android_SetWindowFullscreen() ).
slouken@4998
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@12503
     3
  Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
slouken@4998
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@4998
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@4998
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@4998
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@4998
    22
slouken@6044
    23
#if SDL_VIDEO_DRIVER_ANDROID
slouken@6044
    24
slouken@8803
    25
#include "SDL_syswm.h"
slouken@4998
    26
#include "../SDL_sysvideo.h"
philipp@7254
    27
#include "../../events/SDL_keyboard_c.h"
philipp@7254
    28
#include "../../events/SDL_mouse_c.h"
slouken@12017
    29
#include "../../events/SDL_windowevents_c.h"
slouken@12255
    30
#include "../../core/android/SDL_android.h"
slouken@4998
    31
slouken@4998
    32
#include "SDL_androidvideo.h"
slouken@4998
    33
#include "SDL_androidwindow.h"
slouken@11270
    34
#include "SDL_hints.h"
slouken@4998
    35
sylvain@12494
    36
/* Currently only one window */
sylvain@12494
    37
SDL_Window *Android_Window = NULL;
sylvain@12494
    38
slouken@4998
    39
int
slouken@4998
    40
Android_CreateWindow(_THIS, SDL_Window * window)
slouken@4998
    41
{
gabomdq@7659
    42
    SDL_WindowData *data;
sylvain@12495
    43
    int retval = 0;
sylvain@12496
    44
sylvain@12498
    45
    SDL_LockMutex(Android_ActivityMutex);
sylvain@12496
    46
slouken@5001
    47
    if (Android_Window) {
sylvain@12495
    48
        retval = SDL_SetError("Android only supports one window");
sylvain@12495
    49
        goto endfunction;
slouken@5001
    50
    }
sylvain@12496
    51
gabomdq@6330
    52
    Android_PauseSem = SDL_CreateSemaphore(0);
gabomdq@6330
    53
    Android_ResumeSem = SDL_CreateSemaphore(0);
slouken@5001
    54
slouken@11270
    55
    /* Set orientation */
slouken@11270
    56
    Android_JNI_SetOrientation(window->w, window->h, window->flags & SDL_WINDOW_RESIZABLE, SDL_GetHint(SDL_HINT_ORIENTATIONS));
slouken@11270
    57
slouken@4998
    58
    /* Adjust the window data to match the screen */
slouken@4998
    59
    window->x = 0;
slouken@4998
    60
    window->y = 0;
slouken@12012
    61
    window->w = Android_SurfaceWidth;
slouken@12012
    62
    window->h = Android_SurfaceHeight;
slouken@4998
    63
slouken@5222
    64
    window->flags &= ~SDL_WINDOW_RESIZABLE;     /* window is NEVER resizeable */
slouken@6262
    65
    window->flags &= ~SDL_WINDOW_HIDDEN;
slouken@5222
    66
    window->flags |= SDL_WINDOW_SHOWN;          /* only one window on Android */
slouken@7191
    67
    window->flags |= SDL_WINDOW_INPUT_FOCUS;    /* always has input focus */
slouken@5222
    68
slouken@6651
    69
    /* One window, it always has focus */
slouken@6651
    70
    SDL_SetMouseFocus(window);
slouken@6654
    71
    SDL_SetKeyboardFocus(window);
sylvain@12496
    72
gabomdq@7659
    73
    data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
gabomdq@7659
    74
    if (!data) {
sylvain@12495
    75
        retval = SDL_OutOfMemory();
sylvain@12495
    76
        goto endfunction;
gabomdq@7659
    77
    }
sylvain@12496
    78
gabomdq@7659
    79
    data->native_window = Android_JNI_GetNativeWindow();
sylvain@12496
    80
gabomdq@7659
    81
    if (!data->native_window) {
gabomdq@7659
    82
        SDL_free(data);
sylvain@12495
    83
        retval = SDL_SetError("Could not fetch native window");
sylvain@12495
    84
        goto endfunction;
gabomdq@7659
    85
    }
slouken@6651
    86
slouken@11006
    87
    /* Do not create EGLSurface for Vulkan window since it will then make the window
slouken@11006
    88
       incompatible with vkCreateAndroidSurfaceKHR */
slouken@11006
    89
    if ((window->flags & SDL_WINDOW_VULKAN) == 0) {
slouken@11006
    90
        data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->native_window);
slouken@11006
    91
slouken@11006
    92
        if (data->egl_surface == EGL_NO_SURFACE) {
slouken@11006
    93
            ANativeWindow_release(data->native_window);
slouken@11006
    94
            SDL_free(data);
sylvain@12497
    95
            retval = -1;
sylvain@12495
    96
            goto endfunction;
slouken@11006
    97
        }
gabomdq@7659
    98
    }
gabomdq@7659
    99
gabomdq@7659
   100
    window->driverdata = data;
gabomdq@7659
   101
    Android_Window = window;
sylvain@12495
   102
sylvain@12495
   103
endfunction:
sylvain@12496
   104
sylvain@12498
   105
    SDL_UnlockMutex(Android_ActivityMutex);
sylvain@12496
   106
sylvain@12495
   107
    return retval;
slouken@4998
   108
}
slouken@4998
   109
slouken@4998
   110
void
sylvain@12494
   111
Android_SetWindowTitle(_THIS, SDL_Window *window)
slouken@4998
   112
{
slouken@4998
   113
    Android_JNI_SetActivityTitle(window->title);
slouken@4998
   114
}
slouken@4998
   115
slouken@4998
   116
void
sylvain@12494
   117
Android_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
slouken@11865
   118
{
sylvain@12512
   119
    SDL_LockMutex(Android_ActivityMutex);
sylvain@12512
   120
sylvain@12512
   121
    if (window == Android_Window) {
sylvain@12512
   122
sylvain@12512
   123
        /* If the window is being destroyed don't change visible state */
sylvain@12512
   124
        if (!window->is_destroying) {
sylvain@12512
   125
            Android_JNI_SetWindowStyle(fullscreen);
sylvain@12512
   126
        }
sylvain@12512
   127
sylvain@12512
   128
        /* Ensure our size matches reality after we've executed the window style change.
sylvain@12512
   129
         *
sylvain@12512
   130
         * It is possible that we've set width and height to the full-size display, but on
sylvain@12512
   131
         * Samsung DeX or Chromebooks or other windowed Android environemtns, our window may
sylvain@12512
   132
         * still not be the full display size.
sylvain@12512
   133
         */
sylvain@12512
   134
        if (!SDL_IsDeXMode() && !SDL_IsChromebook()) {
sylvain@12512
   135
            goto endfunction;
sylvain@12512
   136
        }
sylvain@12512
   137
sylvain@12512
   138
        SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
sylvain@12512
   139
sylvain@12512
   140
        if (!data || !data->native_window) {
sylvain@12512
   141
            goto endfunction;
sylvain@12512
   142
        }
sylvain@12512
   143
sylvain@12512
   144
        int old_w = window->w;
sylvain@12512
   145
        int old_h = window->h;
sylvain@12512
   146
sylvain@12512
   147
        int new_w = ANativeWindow_getWidth(data->native_window);
sylvain@12512
   148
        int new_h = ANativeWindow_getHeight(data->native_window);
sylvain@12512
   149
sylvain@12512
   150
        if (old_w != new_w || old_h != new_h) {
sylvain@12512
   151
            SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, new_w, new_h);
sylvain@12512
   152
        }
slouken@12305
   153
    }
slouken@12017
   154
sylvain@12512
   155
endfunction:
slouken@12255
   156
sylvain@12512
   157
    SDL_UnlockMutex(Android_ActivityMutex);
slouken@11865
   158
}
slouken@11865
   159
slouken@11865
   160
void
sylvain@12494
   161
Android_DestroyWindow(_THIS, SDL_Window *window)
sylvain@12496
   162
{
sylvain@12498
   163
    SDL_LockMutex(Android_ActivityMutex);
sylvain@12496
   164
slouken@5001
   165
    if (window == Android_Window) {
slouken@5001
   166
        Android_Window = NULL;
gabomdq@6330
   167
        if (Android_PauseSem) SDL_DestroySemaphore(Android_PauseSem);
gabomdq@6330
   168
        if (Android_ResumeSem) SDL_DestroySemaphore(Android_ResumeSem);
gabomdq@6330
   169
        Android_PauseSem = NULL;
gabomdq@6330
   170
        Android_ResumeSem = NULL;
sylvain@12496
   171
sylvain@12495
   172
        if (window->driverdata) {
sylvain@12495
   173
            SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
gabomdq@7986
   174
            if (data->egl_surface != EGL_NO_SURFACE) {
gabomdq@7986
   175
                SDL_EGL_DestroySurface(_this, data->egl_surface);
gabomdq@7986
   176
            }
slouken@8799
   177
            if (data->native_window) {
gabomdq@7659
   178
                ANativeWindow_release(data->native_window);
gabomdq@7659
   179
            }
gabomdq@7659
   180
            SDL_free(window->driverdata);
gabomdq@7659
   181
            window->driverdata = NULL;
gabomdq@7659
   182
        }
slouken@5001
   183
    }
sylvain@12496
   184
sylvain@12498
   185
    SDL_UnlockMutex(Android_ActivityMutex);
slouken@4998
   186
}
slouken@4998
   187
slouken@8799
   188
SDL_bool
sylvain@12494
   189
Android_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *info)
slouken@8799
   190
{
slouken@8799
   191
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@8799
   192
slouken@8799
   193
    if (info->version.major == SDL_MAJOR_VERSION &&
slouken@8799
   194
        info->version.minor == SDL_MINOR_VERSION) {
slouken@8799
   195
        info->subsystem = SDL_SYSWM_ANDROID;
slouken@8799
   196
        info->info.android.window = data->native_window;
slouken@8799
   197
        info->info.android.surface = data->egl_surface;
slouken@8799
   198
        return SDL_TRUE;
slouken@8799
   199
    } else {
philipp@10945
   200
        SDL_SetError("Application not compiled with SDL %d.%d",
slouken@8799
   201
                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
slouken@8799
   202
        return SDL_FALSE;
slouken@8799
   203
    }
slouken@8799
   204
}
slouken@8799
   205
slouken@6044
   206
#endif /* SDL_VIDEO_DRIVER_ANDROID */
slouken@6044
   207
slouken@4998
   208
/* vi: set ts=4 sw=4 expandtab: */