diff options
Diffstat (limited to 'contrib/SDL-3.2.8/src/video/android/SDL_androidvideo.c')
| -rw-r--r-- | contrib/SDL-3.2.8/src/video/android/SDL_androidvideo.c | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidvideo.c b/contrib/SDL-3.2.8/src/video/android/SDL_androidvideo.c new file mode 100644 index 0000000..b154ff7 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidvideo.c | |||
| @@ -0,0 +1,331 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | #ifdef SDL_VIDEO_DRIVER_ANDROID | ||
| 24 | |||
| 25 | // Android SDL video driver implementation | ||
| 26 | |||
| 27 | #include "../SDL_sysvideo.h" | ||
| 28 | #include "../SDL_pixels_c.h" | ||
| 29 | #include "../../events/SDL_events_c.h" | ||
| 30 | #include "../../events/SDL_windowevents_c.h" | ||
| 31 | |||
| 32 | #include "SDL_androidvideo.h" | ||
| 33 | #include "SDL_androidgl.h" | ||
| 34 | #include "SDL_androidclipboard.h" | ||
| 35 | #include "SDL_androidevents.h" | ||
| 36 | #include "SDL_androidkeyboard.h" | ||
| 37 | #include "SDL_androidmouse.h" | ||
| 38 | #include "SDL_androidtouch.h" | ||
| 39 | #include "SDL_androidwindow.h" | ||
| 40 | #include "SDL_androidvulkan.h" | ||
| 41 | #include "SDL_androidmessagebox.h" | ||
| 42 | |||
| 43 | #define ANDROID_VID_DRIVER_NAME "android" | ||
| 44 | |||
| 45 | // Initialization/Query functions | ||
| 46 | static bool Android_VideoInit(SDL_VideoDevice *_this); | ||
| 47 | static void Android_VideoQuit(SDL_VideoDevice *_this); | ||
| 48 | |||
| 49 | #include "../SDL_egl_c.h" | ||
| 50 | #define Android_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal | ||
| 51 | #define Android_GLES_UnloadLibrary SDL_EGL_UnloadLibrary | ||
| 52 | #define Android_GLES_SetSwapInterval SDL_EGL_SetSwapInterval | ||
| 53 | #define Android_GLES_GetSwapInterval SDL_EGL_GetSwapInterval | ||
| 54 | #define Android_GLES_DestroyContext SDL_EGL_DestroyContext | ||
| 55 | |||
| 56 | // Android driver bootstrap functions | ||
| 57 | |||
| 58 | // These are filled in with real values in Android_SetScreenResolution on init (before SDL_main()) | ||
| 59 | int Android_SurfaceWidth = 0; | ||
| 60 | int Android_SurfaceHeight = 0; | ||
| 61 | static int Android_DeviceWidth = 0; | ||
| 62 | static int Android_DeviceHeight = 0; | ||
| 63 | static Uint32 Android_ScreenFormat = SDL_PIXELFORMAT_RGB565; // Default SurfaceView format, in case this is queried before being filled | ||
| 64 | float Android_ScreenDensity = 1.0f; | ||
| 65 | static float Android_ScreenRate = 0.0f; | ||
| 66 | static SDL_DisplayOrientation Android_ScreenOrientation = SDL_ORIENTATION_UNKNOWN; | ||
| 67 | int Android_SafeInsetLeft = 0; | ||
| 68 | int Android_SafeInsetRight = 0; | ||
| 69 | int Android_SafeInsetTop = 0; | ||
| 70 | int Android_SafeInsetBottom = 0; | ||
| 71 | static SDL_SystemTheme Android_SystemTheme; | ||
| 72 | |||
| 73 | static bool Android_SuspendScreenSaver(SDL_VideoDevice *_this) | ||
| 74 | { | ||
| 75 | return Android_JNI_SuspendScreenSaver(_this->suspend_screensaver); | ||
| 76 | } | ||
| 77 | |||
| 78 | static void Android_DeleteDevice(SDL_VideoDevice *device) | ||
| 79 | { | ||
| 80 | SDL_free(device->internal); | ||
| 81 | SDL_free(device); | ||
| 82 | } | ||
| 83 | |||
| 84 | static SDL_VideoDevice *Android_CreateDevice(void) | ||
| 85 | { | ||
| 86 | SDL_VideoDevice *device; | ||
| 87 | SDL_VideoData *data; | ||
| 88 | |||
| 89 | // Initialize all variables that we clean on shutdown | ||
| 90 | device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); | ||
| 91 | if (!device) { | ||
| 92 | return NULL; | ||
| 93 | } | ||
| 94 | |||
| 95 | data = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); | ||
| 96 | if (!data) { | ||
| 97 | SDL_free(device); | ||
| 98 | return NULL; | ||
| 99 | } | ||
| 100 | |||
| 101 | device->internal = data; | ||
| 102 | device->system_theme = Android_SystemTheme; | ||
| 103 | |||
| 104 | // Set the function pointers | ||
| 105 | device->VideoInit = Android_VideoInit; | ||
| 106 | device->VideoQuit = Android_VideoQuit; | ||
| 107 | |||
| 108 | device->CreateSDLWindow = Android_CreateWindow; | ||
| 109 | device->SetWindowTitle = Android_SetWindowTitle; | ||
| 110 | device->SetWindowFullscreen = Android_SetWindowFullscreen; | ||
| 111 | device->MinimizeWindow = Android_MinimizeWindow; | ||
| 112 | device->SetWindowResizable = Android_SetWindowResizable; | ||
| 113 | device->DestroyWindow = Android_DestroyWindow; | ||
| 114 | |||
| 115 | device->free = Android_DeleteDevice; | ||
| 116 | |||
| 117 | // GL pointers | ||
| 118 | #ifdef SDL_VIDEO_OPENGL_EGL | ||
| 119 | device->GL_LoadLibrary = Android_GLES_LoadLibrary; | ||
| 120 | device->GL_GetProcAddress = Android_GLES_GetProcAddress; | ||
| 121 | device->GL_UnloadLibrary = Android_GLES_UnloadLibrary; | ||
| 122 | device->GL_CreateContext = Android_GLES_CreateContext; | ||
| 123 | device->GL_MakeCurrent = Android_GLES_MakeCurrent; | ||
| 124 | device->GL_SetSwapInterval = Android_GLES_SetSwapInterval; | ||
| 125 | device->GL_GetSwapInterval = Android_GLES_GetSwapInterval; | ||
| 126 | device->GL_SwapWindow = Android_GLES_SwapWindow; | ||
| 127 | device->GL_DestroyContext = Android_GLES_DestroyContext; | ||
| 128 | #endif | ||
| 129 | |||
| 130 | #ifdef SDL_VIDEO_VULKAN | ||
| 131 | device->Vulkan_LoadLibrary = Android_Vulkan_LoadLibrary; | ||
| 132 | device->Vulkan_UnloadLibrary = Android_Vulkan_UnloadLibrary; | ||
| 133 | device->Vulkan_GetInstanceExtensions = Android_Vulkan_GetInstanceExtensions; | ||
| 134 | device->Vulkan_CreateSurface = Android_Vulkan_CreateSurface; | ||
| 135 | device->Vulkan_DestroySurface = Android_Vulkan_DestroySurface; | ||
| 136 | #endif | ||
| 137 | |||
| 138 | // Screensaver | ||
| 139 | device->SuspendScreenSaver = Android_SuspendScreenSaver; | ||
| 140 | |||
| 141 | // Screen keyboard | ||
| 142 | device->HasScreenKeyboardSupport = Android_HasScreenKeyboardSupport; | ||
| 143 | device->ShowScreenKeyboard = Android_ShowScreenKeyboard; | ||
| 144 | device->HideScreenKeyboard = Android_HideScreenKeyboard; | ||
| 145 | device->IsScreenKeyboardShown = Android_IsScreenKeyboardShown; | ||
| 146 | |||
| 147 | // Clipboard | ||
| 148 | device->SetClipboardText = Android_SetClipboardText; | ||
| 149 | device->GetClipboardText = Android_GetClipboardText; | ||
| 150 | device->HasClipboardText = Android_HasClipboardText; | ||
| 151 | |||
| 152 | device->device_caps = VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS; | ||
| 153 | |||
| 154 | return device; | ||
| 155 | } | ||
| 156 | |||
| 157 | VideoBootStrap Android_bootstrap = { | ||
| 158 | ANDROID_VID_DRIVER_NAME, "SDL Android video driver", | ||
| 159 | Android_CreateDevice, | ||
| 160 | Android_ShowMessageBox, | ||
| 161 | false | ||
| 162 | }; | ||
| 163 | |||
| 164 | bool Android_VideoInit(SDL_VideoDevice *_this) | ||
| 165 | { | ||
| 166 | SDL_VideoData *videodata = _this->internal; | ||
| 167 | SDL_DisplayID displayID; | ||
| 168 | SDL_VideoDisplay *display; | ||
| 169 | SDL_DisplayMode mode; | ||
| 170 | |||
| 171 | videodata->isPaused = false; | ||
| 172 | videodata->isPausing = false; | ||
| 173 | |||
| 174 | SDL_zero(mode); | ||
| 175 | mode.format = Android_ScreenFormat; | ||
| 176 | mode.w = Android_DeviceWidth; | ||
| 177 | mode.h = Android_DeviceHeight; | ||
| 178 | mode.refresh_rate = Android_ScreenRate; | ||
| 179 | |||
| 180 | displayID = SDL_AddBasicVideoDisplay(&mode); | ||
| 181 | if (displayID == 0) { | ||
| 182 | return false; | ||
| 183 | } | ||
| 184 | display = SDL_GetVideoDisplay(displayID); | ||
| 185 | display->natural_orientation = Android_JNI_GetDisplayNaturalOrientation(); | ||
| 186 | display->current_orientation = Android_JNI_GetDisplayCurrentOrientation(); | ||
| 187 | display->content_scale = Android_ScreenDensity; | ||
| 188 | |||
| 189 | Android_InitTouch(); | ||
| 190 | |||
| 191 | Android_InitMouse(); | ||
| 192 | |||
| 193 | // We're done! | ||
| 194 | return true; | ||
| 195 | } | ||
| 196 | |||
| 197 | void Android_VideoQuit(SDL_VideoDevice *_this) | ||
| 198 | { | ||
| 199 | Android_QuitMouse(); | ||
| 200 | Android_QuitTouch(); | ||
| 201 | } | ||
| 202 | |||
| 203 | void Android_SetScreenResolution(int surfaceWidth, int surfaceHeight, int deviceWidth, int deviceHeight, float density, float rate) | ||
| 204 | { | ||
| 205 | Android_SurfaceWidth = surfaceWidth; | ||
| 206 | Android_SurfaceHeight = surfaceHeight; | ||
| 207 | Android_DeviceWidth = deviceWidth; | ||
| 208 | Android_DeviceHeight = deviceHeight; | ||
| 209 | Android_ScreenDensity = (density > 0.0f) ? density : 1.0f; | ||
| 210 | Android_ScreenRate = rate; | ||
| 211 | } | ||
| 212 | |||
| 213 | static Uint32 format_to_pixelFormat(int format) | ||
| 214 | { | ||
| 215 | Uint32 pf; | ||
| 216 | if (format == AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM) { // 1 | ||
| 217 | pf = SDL_PIXELFORMAT_RGBA8888; | ||
| 218 | } else if (format == AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM) { // 2 | ||
| 219 | pf = SDL_PIXELFORMAT_RGBX8888; | ||
| 220 | } else if (format == AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM) { // 3 | ||
| 221 | pf = SDL_PIXELFORMAT_RGB24; | ||
| 222 | } else if (format == AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM) { // 4 | ||
| 223 | pf = SDL_PIXELFORMAT_RGB565; | ||
| 224 | } else if (format == 5) { | ||
| 225 | pf = SDL_PIXELFORMAT_BGRA8888; | ||
| 226 | } else if (format == 6) { | ||
| 227 | pf = SDL_PIXELFORMAT_RGBA5551; | ||
| 228 | } else if (format == 7) { | ||
| 229 | pf = SDL_PIXELFORMAT_RGBA4444; | ||
| 230 | } else if (format == 0x115) { | ||
| 231 | // HAL_PIXEL_FORMAT_BGR_565 | ||
| 232 | pf = SDL_PIXELFORMAT_RGB565; | ||
| 233 | } else { | ||
| 234 | pf = SDL_PIXELFORMAT_UNKNOWN; | ||
| 235 | } | ||
| 236 | return pf; | ||
| 237 | } | ||
| 238 | |||
| 239 | void Android_SetFormat(int format_wanted, int format_got) | ||
| 240 | { | ||
| 241 | Uint32 pf_wanted; | ||
| 242 | Uint32 pf_got; | ||
| 243 | |||
| 244 | pf_wanted = format_to_pixelFormat(format_wanted); | ||
| 245 | pf_got = format_to_pixelFormat(format_got); | ||
| 246 | |||
| 247 | Android_ScreenFormat = pf_got; | ||
| 248 | |||
| 249 | SDL_Log("pixel format wanted %s (%d), got %s (%d)", | ||
| 250 | SDL_GetPixelFormatName(pf_wanted), format_wanted, | ||
| 251 | SDL_GetPixelFormatName(pf_got), format_got); | ||
| 252 | } | ||
| 253 | |||
| 254 | static void Android_SendOrientationUpdate(void) | ||
| 255 | { | ||
| 256 | /* If we've received a compatible resize event, update the | ||
| 257 | * orientation immediately, otherwise wait for the display | ||
| 258 | * resize event. | ||
| 259 | */ | ||
| 260 | SDL_VideoDevice *device = SDL_GetVideoDevice(); | ||
| 261 | if (device && device->num_displays > 0) { | ||
| 262 | SDL_VideoDisplay *display = device->displays[0]; | ||
| 263 | bool mode_landscape = (display->desktop_mode.w > display->desktop_mode.h); | ||
| 264 | bool sensor_landscape = (Android_ScreenOrientation == SDL_ORIENTATION_LANDSCAPE || Android_ScreenOrientation == SDL_ORIENTATION_LANDSCAPE_FLIPPED); | ||
| 265 | if (sensor_landscape == mode_landscape) { | ||
| 266 | SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_ORIENTATION, Android_ScreenOrientation, 0); | ||
| 267 | } | ||
| 268 | } | ||
| 269 | } | ||
| 270 | |||
| 271 | void Android_SetOrientation(SDL_DisplayOrientation orientation) | ||
| 272 | { | ||
| 273 | Android_ScreenOrientation = orientation; | ||
| 274 | Android_SendOrientationUpdate(); | ||
| 275 | } | ||
| 276 | |||
| 277 | void Android_SendResize(SDL_Window *window) | ||
| 278 | { | ||
| 279 | /* | ||
| 280 | Update the resolution of the desktop mode, so that the window | ||
| 281 | can be properly resized. The screen resolution change can for | ||
| 282 | example happen when the Activity enters or exits immersive mode, | ||
| 283 | which can happen after VideoInit(). | ||
| 284 | */ | ||
| 285 | SDL_VideoDevice *device = SDL_GetVideoDevice(); | ||
| 286 | if (device && device->num_displays > 0) { | ||
| 287 | SDL_VideoDisplay *display = device->displays[0]; | ||
| 288 | SDL_DisplayMode desktop_mode; | ||
| 289 | |||
| 290 | SDL_zero(desktop_mode); | ||
| 291 | desktop_mode.format = Android_ScreenFormat; | ||
| 292 | desktop_mode.w = Android_DeviceWidth; | ||
| 293 | desktop_mode.h = Android_DeviceHeight; | ||
| 294 | desktop_mode.refresh_rate = Android_ScreenRate; | ||
| 295 | SDL_SetDesktopDisplayMode(display, &desktop_mode); | ||
| 296 | Android_SendOrientationUpdate(); | ||
| 297 | } | ||
| 298 | |||
| 299 | if (window) { | ||
| 300 | SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, Android_SurfaceWidth, Android_SurfaceHeight); | ||
| 301 | } | ||
| 302 | } | ||
| 303 | |||
| 304 | void Android_SetWindowSafeAreaInsets(int left, int right, int top, int bottom) | ||
| 305 | { | ||
| 306 | Android_SafeInsetLeft = left; | ||
| 307 | Android_SafeInsetRight = right; | ||
| 308 | Android_SafeInsetTop = top; | ||
| 309 | Android_SafeInsetBottom = bottom; | ||
| 310 | |||
| 311 | if (Android_Window) { | ||
| 312 | SDL_SetWindowSafeAreaInsets(Android_Window, left, right, top, bottom); | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | void Android_SetDarkMode(bool enabled) | ||
| 317 | { | ||
| 318 | SDL_VideoDevice *device = SDL_GetVideoDevice(); | ||
| 319 | |||
| 320 | if (enabled) { | ||
| 321 | Android_SystemTheme = SDL_SYSTEM_THEME_DARK; | ||
| 322 | } else { | ||
| 323 | Android_SystemTheme = SDL_SYSTEM_THEME_LIGHT; | ||
| 324 | } | ||
| 325 | |||
| 326 | if (device) { | ||
| 327 | SDL_SetSystemTheme(Android_SystemTheme); | ||
| 328 | } | ||
| 329 | } | ||
| 330 | |||
| 331 | #endif // SDL_VIDEO_DRIVER_ANDROID | ||
