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 int
Android_Available(void)74 Android_Available(void)
75 {
76 return 1;
77 }
78
79 static void
Android_SuspendScreenSaver(_THIS)80 Android_SuspendScreenSaver(_THIS)
81 {
82 Android_JNI_SuspendScreenSaver(_this->suspend_screensaver);
83 }
84
85 static void
Android_DeleteDevice(SDL_VideoDevice * device)86 Android_DeleteDevice(SDL_VideoDevice *device)
87 {
88 SDL_free(device->driverdata);
89 SDL_free(device);
90 }
91
92 static SDL_VideoDevice *
Android_CreateDevice(int devindex)93 Android_CreateDevice(int devindex)
94 {
95 SDL_VideoDevice *device;
96 SDL_VideoData *data;
97 SDL_bool block_on_pause;
98
99 /* Initialize all variables that we clean on shutdown */
100 device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
101 if (!device) {
102 SDL_OutOfMemory();
103 return NULL;
104 }
105
106 data = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
107 if (!data) {
108 SDL_OutOfMemory();
109 SDL_free(device);
110 return NULL;
111 }
112
113 device->driverdata = data;
114
115 /* Set the function pointers */
116 device->VideoInit = Android_VideoInit;
117 device->VideoQuit = Android_VideoQuit;
118 block_on_pause = SDL_GetHintBoolean(SDL_HINT_ANDROID_BLOCK_ON_PAUSE, SDL_TRUE);
119 if (block_on_pause) {
120 device->PumpEvents = Android_PumpEvents_Blocking;
121 } else {
122 device->PumpEvents = Android_PumpEvents_NonBlocking;
123 }
124
125 device->GetDisplayDPI = Android_GetDisplayDPI;
126
127 device->CreateSDLWindow = Android_CreateWindow;
128 device->SetWindowTitle = Android_SetWindowTitle;
129 device->SetWindowFullscreen = Android_SetWindowFullscreen;
130 device->MinimizeWindow = Android_MinimizeWindow;
131 device->DestroyWindow = Android_DestroyWindow;
132 device->GetWindowWMInfo = Android_GetWindowWMInfo;
133
134 device->free = Android_DeleteDevice;
135
136 /* GL pointers */
137 device->GL_LoadLibrary = Android_GLES_LoadLibrary;
138 device->GL_GetProcAddress = Android_GLES_GetProcAddress;
139 device->GL_UnloadLibrary = Android_GLES_UnloadLibrary;
140 device->GL_CreateContext = Android_GLES_CreateContext;
141 device->GL_MakeCurrent = Android_GLES_MakeCurrent;
142 device->GL_SetSwapInterval = Android_GLES_SetSwapInterval;
143 device->GL_GetSwapInterval = Android_GLES_GetSwapInterval;
144 device->GL_SwapWindow = Android_GLES_SwapWindow;
145 device->GL_DeleteContext = Android_GLES_DeleteContext;
146
147 #if SDL_VIDEO_VULKAN
148 device->Vulkan_LoadLibrary = Android_Vulkan_LoadLibrary;
149 device->Vulkan_UnloadLibrary = Android_Vulkan_UnloadLibrary;
150 device->Vulkan_GetInstanceExtensions = Android_Vulkan_GetInstanceExtensions;
151 device->Vulkan_CreateSurface = Android_Vulkan_CreateSurface;
152 #endif
153
154 /* Screensaver */
155 device->SuspendScreenSaver = Android_SuspendScreenSaver;
156
157 /* Text input */
158 device->StartTextInput = Android_StartTextInput;
159 device->StopTextInput = Android_StopTextInput;
160 device->SetTextInputRect = Android_SetTextInputRect;
161
162 /* Screen keyboard */
163 device->HasScreenKeyboardSupport = Android_HasScreenKeyboardSupport;
164 device->IsScreenKeyboardShown = Android_IsScreenKeyboardShown;
165
166 /* Clipboard */
167 device->SetClipboardText = Android_SetClipboardText;
168 device->GetClipboardText = Android_GetClipboardText;
169 device->HasClipboardText = Android_HasClipboardText;
170
171 return device;
172 }
173
174 VideoBootStrap Android_bootstrap = {
175 ANDROID_VID_DRIVER_NAME, "SDL Android video driver",
176 Android_Available, Android_CreateDevice
177 };
178
179
180 int
Android_VideoInit(_THIS)181 Android_VideoInit(_THIS)
182 {
183 SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
184 int display_index;
185 SDL_VideoDisplay *display;
186 SDL_DisplayMode mode;
187
188 videodata->isPaused = SDL_FALSE;
189 videodata->isPausing = SDL_FALSE;
190
191 mode.format = Android_ScreenFormat;
192 mode.w = Android_DeviceWidth;
193 mode.h = Android_DeviceHeight;
194 mode.refresh_rate = Android_ScreenRate;
195 mode.driverdata = NULL;
196
197 display_index = SDL_AddBasicVideoDisplay(&mode);
198 if (display_index < 0) {
199 return -1;
200 }
201 display = SDL_GetDisplay(display_index);
202 display->orientation = Android_JNI_GetDisplayOrientation();
203
204 SDL_AddDisplayMode(&_this->displays[0], &mode);
205
206 Android_InitKeyboard();
207
208 Android_InitTouch();
209
210 Android_InitMouse();
211
212 /* We're done! */
213 return 0;
214 }
215
216 void
Android_VideoQuit(_THIS)217 Android_VideoQuit(_THIS)
218 {
219 Android_QuitMouse();
220 Android_QuitTouch();
221 }
222
223 int
Android_GetDisplayDPI(_THIS,SDL_VideoDisplay * display,float * ddpi,float * hdpi,float * vdpi)224 Android_GetDisplayDPI(_THIS, SDL_VideoDisplay *display, float *ddpi, float *hdpi, float *vdpi)
225 {
226 return Android_JNI_GetDisplayDPI(ddpi, hdpi, vdpi);
227 }
228
229 void
Android_SetScreenResolution(int surfaceWidth,int surfaceHeight,int deviceWidth,int deviceHeight,Uint32 format,float rate)230 Android_SetScreenResolution(int surfaceWidth, int surfaceHeight, int deviceWidth, int deviceHeight, Uint32 format, float rate)
231 {
232 Android_SurfaceWidth = surfaceWidth;
233 Android_SurfaceHeight = surfaceHeight;
234 Android_DeviceWidth = deviceWidth;
235 Android_DeviceHeight = deviceHeight;
236 Android_ScreenFormat = format;
237 Android_ScreenRate = (int)rate;
238 }
239
Android_SendResize(SDL_Window * window)240 void Android_SendResize(SDL_Window *window)
241 {
242 /*
243 Update the resolution of the desktop mode, so that the window
244 can be properly resized. The screen resolution change can for
245 example happen when the Activity enters or exits immersive mode,
246 which can happen after VideoInit().
247 */
248 SDL_VideoDevice *device = SDL_GetVideoDevice();
249 if (device && device->num_displays > 0)
250 {
251 SDL_VideoDisplay *display = &device->displays[0];
252 display->desktop_mode.format = Android_ScreenFormat;
253 display->desktop_mode.w = Android_DeviceWidth;
254 display->desktop_mode.h = Android_DeviceHeight;
255 display->desktop_mode.refresh_rate = Android_ScreenRate;
256 }
257
258 if (window) {
259 /* Force the current mode to match the resize otherwise the SDL_WINDOWEVENT_RESTORED event
260 * will fall back to the old mode */
261 SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
262 display->display_modes[0].format = Android_ScreenFormat;
263 display->display_modes[0].w = Android_DeviceWidth;
264 display->display_modes[0].h = Android_DeviceHeight;
265 display->display_modes[0].refresh_rate = Android_ScreenRate;
266 display->current_mode = display->display_modes[0];
267
268 SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, Android_SurfaceWidth, Android_SurfaceHeight);
269 }
270 }
271
272 #endif /* SDL_VIDEO_DRIVER_ANDROID */
273
274 /* vi: set ts=4 sw=4 expandtab: */
275