Imported Upstream version 2.0.14
[platform/upstream/SDL.git] / src / video / android / SDL_androidvideo.c
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
4
5   This software is provided 'as-is', without any express or implied
6   warranty.  In no event will the authors be held liable for any damages
7   arising from the use of this software.
8
9   Permission is granted to anyone to use this software for any purpose,
10   including commercial applications, and to alter it and redistribute it
11   freely, subject to the following restrictions:
12
13   1. The origin of this software must not be misrepresented; you must not
14      claim that you wrote the original software. If you use this software
15      in a product, an acknowledgment in the product documentation would be
16      appreciated but is not required.
17   2. Altered source versions must be plainly marked as such, and must not be
18      misrepresented as being the original software.
19   3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22
23 #if SDL_VIDEO_DRIVER_ANDROID
24
25 /* Android SDL video driver implementation */
26
27 #include "SDL_video.h"
28 #include "SDL_mouse.h"
29 #include "SDL_hints.h"
30 #include "../SDL_sysvideo.h"
31 #include "../SDL_pixels_c.h"
32 #include "../../events/SDL_events_c.h"
33 #include "../../events/SDL_windowevents_c.h"
34
35 #include "SDL_androidvideo.h"
36 #include "SDL_androidgl.h"
37 #include "SDL_androidclipboard.h"
38 #include "SDL_androidevents.h"
39 #include "SDL_androidkeyboard.h"
40 #include "SDL_androidmouse.h"
41 #include "SDL_androidtouch.h"
42 #include "SDL_androidwindow.h"
43 #include "SDL_androidvulkan.h"
44
45 #define ANDROID_VID_DRIVER_NAME "Android"
46
47 /* Initialization/Query functions */
48 static int Android_VideoInit(_THIS);
49 static void Android_VideoQuit(_THIS);
50 int Android_GetDisplayDPI(_THIS, SDL_VideoDisplay *display, float *ddpi, float *hdpi, float *vdpi);
51
52 #include "../SDL_egl_c.h"
53 #define Android_GLES_GetProcAddress SDL_EGL_GetProcAddress
54 #define Android_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
55 #define Android_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
56 #define Android_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
57 #define Android_GLES_DeleteContext SDL_EGL_DeleteContext
58
59 /* Android driver bootstrap functions */
60
61
62 /* These are filled in with real values in Android_SetScreenResolution on init (before SDL_main()) */
63 int Android_SurfaceWidth           = 0;
64 int Android_SurfaceHeight          = 0;
65 static int Android_DeviceWidth     = 0;
66 static int Android_DeviceHeight    = 0;
67 static Uint32 Android_ScreenFormat = SDL_PIXELFORMAT_UNKNOWN;
68 static int Android_ScreenRate      = 0;
69 SDL_sem *Android_PauseSem          = NULL;
70 SDL_sem *Android_ResumeSem         = NULL;
71 SDL_mutex *Android_ActivityMutex   = NULL;
72
73 static void
74 Android_SuspendScreenSaver(_THIS)
75 {
76     Android_JNI_SuspendScreenSaver(_this->suspend_screensaver);
77 }
78
79 static void
80 Android_DeleteDevice(SDL_VideoDevice *device)
81 {
82     SDL_free(device->driverdata);
83     SDL_free(device);
84 }
85
86 static SDL_VideoDevice *
87 Android_CreateDevice(int devindex)
88 {
89     SDL_VideoDevice *device;
90     SDL_VideoData *data;
91     SDL_bool block_on_pause;
92
93     /* Initialize all variables that we clean on shutdown */
94     device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
95     if (!device) {
96         SDL_OutOfMemory();
97         return NULL;
98     }
99
100     data = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
101     if (!data) {
102         SDL_OutOfMemory();
103         SDL_free(device);
104         return NULL;
105     }
106
107     device->driverdata = data;
108
109     /* Set the function pointers */
110     device->VideoInit = Android_VideoInit;
111     device->VideoQuit = Android_VideoQuit;
112     block_on_pause = SDL_GetHintBoolean(SDL_HINT_ANDROID_BLOCK_ON_PAUSE, SDL_TRUE);
113     if (block_on_pause) {
114         device->PumpEvents = Android_PumpEvents_Blocking;
115     } else {
116         device->PumpEvents = Android_PumpEvents_NonBlocking;
117     }
118
119     device->GetDisplayDPI = Android_GetDisplayDPI;
120
121     device->CreateSDLWindow = Android_CreateWindow;
122     device->SetWindowTitle = Android_SetWindowTitle;
123     device->SetWindowFullscreen = Android_SetWindowFullscreen;
124     device->MinimizeWindow = Android_MinimizeWindow;
125     device->DestroyWindow = Android_DestroyWindow;
126     device->GetWindowWMInfo = Android_GetWindowWMInfo;
127
128     device->free = Android_DeleteDevice;
129
130     /* GL pointers */
131     device->GL_LoadLibrary = Android_GLES_LoadLibrary;
132     device->GL_GetProcAddress = Android_GLES_GetProcAddress;
133     device->GL_UnloadLibrary = Android_GLES_UnloadLibrary;
134     device->GL_CreateContext = Android_GLES_CreateContext;
135     device->GL_MakeCurrent = Android_GLES_MakeCurrent;
136     device->GL_SetSwapInterval = Android_GLES_SetSwapInterval;
137     device->GL_GetSwapInterval = Android_GLES_GetSwapInterval;
138     device->GL_SwapWindow = Android_GLES_SwapWindow;
139     device->GL_DeleteContext = Android_GLES_DeleteContext;
140
141 #if SDL_VIDEO_VULKAN
142     device->Vulkan_LoadLibrary = Android_Vulkan_LoadLibrary;
143     device->Vulkan_UnloadLibrary = Android_Vulkan_UnloadLibrary;
144     device->Vulkan_GetInstanceExtensions = Android_Vulkan_GetInstanceExtensions;
145     device->Vulkan_CreateSurface = Android_Vulkan_CreateSurface;
146 #endif
147
148     /* Screensaver */
149     device->SuspendScreenSaver = Android_SuspendScreenSaver;
150
151     /* Text input */
152     device->StartTextInput = Android_StartTextInput;
153     device->StopTextInput = Android_StopTextInput;
154     device->SetTextInputRect = Android_SetTextInputRect;
155
156     /* Screen keyboard */
157     device->HasScreenKeyboardSupport = Android_HasScreenKeyboardSupport;
158     device->IsScreenKeyboardShown = Android_IsScreenKeyboardShown;
159
160     /* Clipboard */
161     device->SetClipboardText = Android_SetClipboardText;
162     device->GetClipboardText = Android_GetClipboardText;
163     device->HasClipboardText = Android_HasClipboardText;
164
165     return device;
166 }
167
168 VideoBootStrap Android_bootstrap = {
169     ANDROID_VID_DRIVER_NAME, "SDL Android video driver",
170     Android_CreateDevice
171 };
172
173
174 int
175 Android_VideoInit(_THIS)
176 {
177     SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
178     int display_index;
179     SDL_VideoDisplay *display;
180     SDL_DisplayMode mode;
181
182     videodata->isPaused  = SDL_FALSE;
183     videodata->isPausing = SDL_FALSE;
184     videodata->pauseAudio = SDL_GetHintBoolean(SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO, SDL_TRUE);
185
186     mode.format          = Android_ScreenFormat;
187     mode.w               = Android_DeviceWidth;
188     mode.h               = Android_DeviceHeight;
189     mode.refresh_rate    = Android_ScreenRate;
190     mode.driverdata      = NULL;
191
192     display_index = SDL_AddBasicVideoDisplay(&mode);
193     if (display_index < 0) {
194         return -1;
195     }
196     display = SDL_GetDisplay(display_index);
197     display->orientation = Android_JNI_GetDisplayOrientation();    
198
199     SDL_AddDisplayMode(&_this->displays[0], &mode);
200
201     Android_InitKeyboard();
202
203     Android_InitTouch();
204
205     Android_InitMouse();
206
207     /* We're done! */
208     return 0;
209 }
210
211 void
212 Android_VideoQuit(_THIS)
213 {
214     Android_QuitMouse();
215     Android_QuitTouch();
216 }
217
218 int
219 Android_GetDisplayDPI(_THIS, SDL_VideoDisplay *display, float *ddpi, float *hdpi, float *vdpi)
220 {
221     return Android_JNI_GetDisplayDPI(ddpi, hdpi, vdpi);
222 }
223
224 void
225 Android_SetScreenResolution(int surfaceWidth, int surfaceHeight, int deviceWidth, int deviceHeight, Uint32 format, float rate)
226 {
227     Android_SurfaceWidth  = surfaceWidth;
228     Android_SurfaceHeight = surfaceHeight;
229     Android_DeviceWidth   = deviceWidth;
230     Android_DeviceHeight  = deviceHeight;
231     Android_ScreenFormat  = format;
232     Android_ScreenRate    = (int)rate;
233 }
234
235 void Android_SendResize(SDL_Window *window)
236 {
237     /*
238       Update the resolution of the desktop mode, so that the window
239       can be properly resized. The screen resolution change can for
240       example happen when the Activity enters or exits immersive mode,
241       which can happen after VideoInit().
242     */
243     SDL_VideoDevice *device = SDL_GetVideoDevice();
244     if (device && device->num_displays > 0)
245     {
246         SDL_VideoDisplay *display          = &device->displays[0];
247         display->desktop_mode.format       = Android_ScreenFormat;
248         display->desktop_mode.w            = Android_DeviceWidth;
249         display->desktop_mode.h            = Android_DeviceHeight;
250         display->desktop_mode.refresh_rate = Android_ScreenRate;
251     }
252
253     if (window) {
254         /* Force the current mode to match the resize otherwise the SDL_WINDOWEVENT_RESTORED event
255          * will fall back to the old mode */
256         SDL_VideoDisplay *display              = SDL_GetDisplayForWindow(window);
257         display->display_modes[0].format       = Android_ScreenFormat;
258         display->display_modes[0].w            = Android_DeviceWidth;
259         display->display_modes[0].h            = Android_DeviceHeight;
260         display->display_modes[0].refresh_rate = Android_ScreenRate;
261         display->current_mode                  = display->display_modes[0];
262
263         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, Android_SurfaceWidth, Android_SurfaceHeight);
264     }
265 }
266
267 #endif /* SDL_VIDEO_DRIVER_ANDROID */
268
269 /* vi: set ts=4 sw=4 expandtab: */