diff --git a/CMakeLists.txt b/CMakeLists.txt index 398b36eb..913538a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,10 +24,11 @@ if (DEFINED GLFW_USE_WAYLAND AND UNIX AND NOT APPLE) "GLFW_USE_WAYLAND has been removed; delete the CMake cache and set GLFW_BUILD_WAYLAND and GLFW_BUILD_X11 instead") endif() -cmake_dependent_option(GLFW_BUILD_WIN32 "Build support for Win32" ON "WIN32" OFF) -cmake_dependent_option(GLFW_BUILD_COCOA "Build support for Cocoa" ON "APPLE" OFF) -cmake_dependent_option(GLFW_BUILD_X11 "Build support for X11" ON "UNIX;NOT APPLE" OFF) -cmake_dependent_option(GLFW_BUILD_WAYLAND "Build support for Wayland" ON "UNIX;NOT APPLE" OFF) +cmake_dependent_option(GLFW_BUILD_WIN32 "Build support for Win32" ON "WIN32;NOT ANDROID" OFF) +cmake_dependent_option(GLFW_BUILD_COCOA "Build support for Cocoa" ON "APPLE;NOT ANDROID" OFF) +cmake_dependent_option(GLFW_BUILD_X11 "Build support for X11" ON "UNIX;NOT APPLE;NOT ANDROID" OFF) +cmake_dependent_option(GLFW_BUILD_WAYLAND "Build support for Wayland" ON "UNIX;NOT APPLE;NOT ANDROID" OFF) +cmake_dependent_option(GLFW_BUILD_ANDROID "Build support for Android" ON "ANDROID" OFF) cmake_dependent_option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on hybrid systems" OFF "WIN32" OFF) @@ -66,6 +67,9 @@ endif() if (GLFW_BUILD_X11) message(STATUS "Including X11 support") endif() +if (GLFW_BUILD_ANDROID) + message(STATUS "Including Android support") +endif() #-------------------------------------------------------------------- # Apply Microsoft C runtime library option diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 79b06288..477df47b 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1131,7 +1131,7 @@ extern "C" { #define GLFW_WIN32_SHOWDEFAULT 0x00025002 /*! @brief Wayland specific * [window hint](@ref GLFW_WAYLAND_APP_ID_hint). - * + * * Allows specification of the Wayland app_id. */ #define GLFW_WAYLAND_APP_ID 0x00026001 @@ -1341,7 +1341,8 @@ extern "C" { #define GLFW_PLATFORM_COCOA 0x00060002 #define GLFW_PLATFORM_WAYLAND 0x00060003 #define GLFW_PLATFORM_X11 0x00060004 -#define GLFW_PLATFORM_NULL 0x00060005 +#define GLFW_PLATFORM_ANDROID 0x00060005 +#define GLFW_PLATFORM_NULL 0x00060006 /*! @} */ #define GLFW_DONT_CARE -1 diff --git a/include/GLFW/glfw3native.h b/include/GLFW/glfw3native.h index 011b239c..4d1bf3ee 100644 --- a/include/GLFW/glfw3native.h +++ b/include/GLFW/glfw3native.h @@ -155,6 +155,10 @@ extern "C" { #include #endif + #if defined(GLFW_EXPOSE_NATIVE_ANDROID) + #include + #endif + #endif /*GLFW_NATIVE_INCLUDE_NONE*/ @@ -655,6 +659,12 @@ GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width, int* height GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* window); #endif +#if defined(GLFW_EXPOSE_NATIVE_ANDROID) +/*! @brief Returns the `struct android_app` of the specified window. + */ +GLFWAPI struct android_app* glfwGetAndroidApp(GLFWwindow* window); +#endif + #ifdef __cplusplus } #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1a085b2b..a4b5268b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -57,6 +57,14 @@ if (GLFW_BUILD_WAYLAND) wl_monitor.c wl_window.c) endif() +if (GLFW_BUILD_ANDROID) + target_compile_definitions(glfw PRIVATE _GLFW_ANDROID) + target_include_directories(glfw PRIVATE "${ANDROID_NDK}/sources/android/native_app_glue") + target_sources(glfw PRIVATE android_platform.h android_joystick.h android_init.c + android_monitor.c android_window.c android_joystick.c + "${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c") +endif() + if (GLFW_BUILD_X11 OR GLFW_BUILD_WAYLAND) if (CMAKE_SYSTEM_NAME STREQUAL "Linux") target_sources(glfw PRIVATE linux_joystick.h linux_joystick.c) diff --git a/src/android_init.c b/src/android_init.c new file mode 100644 index 00000000..ba6ebdd9 --- /dev/null +++ b/src/android_init.c @@ -0,0 +1,203 @@ +//======================================================================== +// GLFW 3.5 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2024 kunitoki +// Copyright (c) 2017 Curi0 +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#include +#include +#include + +#include "internal.h" + +struct android_app* _globalAndroidApp = NULL; + +extern int main(); + +void handleAppCmd(struct android_app* app, int32_t cmd) +{ + switch (cmd) + { + case APP_CMD_START: + break; + + case APP_CMD_RESUME: + //_glfwInputWindowIconify(_glfw.windowListHead, GLFW_FALSE); + break; + + case APP_CMD_PAUSE: + //_glfwInputWindowIconify(_glfw.windowListHead, GLFW_TRUE); + break; + + case APP_CMD_STOP: + break; + + case APP_CMD_DESTROY: + break; + + case APP_CMD_INIT_WINDOW: + break; + + case APP_CMD_TERM_WINDOW: + //_glfwInputWindowCloseRequest(_glfw.windowListHead); + break; + + case APP_CMD_LOST_FOCUS: + //_glfwInputWindowFocus(_glfw.windowListHead, GLFW_FALSE); + break; + + case APP_CMD_GAINED_FOCUS: + //_glfwInputWindowFocus(_glfw.windowListHead, GLFW_TRUE); + break; + + case APP_CMD_WINDOW_RESIZED: + _glfwInputWindowSize(_glfw.windowListHead, ANativeWindow_getWidth(app->window), ANativeWindow_getHeight(app->window)); + break; + + case APP_CMD_WINDOW_REDRAW_NEEDED: + _glfwInputWindowDamage(_glfw.windowListHead); + break; + + case APP_CMD_CONTENT_RECT_CHANGED: + _glfwInputFramebufferSize(_glfw.windowListHead, ANativeWindow_getWidth(app->window), ANativeWindow_getHeight(app->window)); + break; + + case APP_CMD_CONFIG_CHANGED: + break; + + case APP_CMD_INPUT_CHANGED: + break; + } +} + +// Android Entry Point +void android_main(struct android_app* app) +{ + app_dummy(); + + app->onAppCmd = handleAppCmd; + + _globalAndroidApp = app; + + main(); +} + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +GLFWbool _glfwConnectAndroid(int platformID, _GLFWplatform* platform) +{ + const _GLFWplatform android = + { + .platformID = GLFW_PLATFORM_ANDROID, + .init = _glfwInitAndroid, + .terminate = _glfwTerminateAndroid, + .getCursorPos = _glfwGetCursorPosAndroid, + .setCursorPos = _glfwSetCursorPosAndroid, + .setCursorMode = _glfwSetCursorModeAndroid, + .setRawMouseMotion = _glfwSetRawMouseMotionAndroid, + .rawMouseMotionSupported = _glfwRawMouseMotionSupportedAndroid, + .createCursor = _glfwCreateCursorAndroid, + .createStandardCursor = _glfwCreateStandardCursorAndroid, + .destroyCursor = _glfwDestroyCursorAndroid, + .setCursor = _glfwSetCursorAndroid, + .getScancodeName = _glfwGetScancodeNameAndroid, + .getKeyScancode = _glfwGetKeyScancodeAndroid, + .setClipboardString = _glfwSetClipboardStringAndroid, + .getClipboardString = _glfwGetClipboardStringAndroid, + .initJoysticks = _glfwInitJoysticksAndroid, + .terminateJoysticks = _glfwTerminateJoysticksAndroid, + .pollJoystick = _glfwPollJoystickAndroid, + .getMappingName = _glfwGetMappingNameAndroid, + .updateGamepadGUID = _glfwUpdateGamepadGUIDAndroid, + .freeMonitor = _glfwFreeMonitorAndroid, + .getMonitorPos = _glfwGetMonitorPosAndroid, + .getMonitorContentScale = _glfwGetMonitorContentScaleAndroid, + .getMonitorWorkarea = _glfwGetMonitorWorkareaAndroid, + .getVideoModes = _glfwGetVideoModesAndroid, + .getVideoMode = _glfwGetVideoModeAndroid, + .getGammaRamp = _glfwGetGammaRampAndroid, + .setGammaRamp = _glfwSetGammaRampAndroid, + .createWindow = _glfwCreateWindowAndroid, + .destroyWindow = _glfwDestroyWindowAndroid, + .setWindowTitle = _glfwSetWindowTitleAndroid, + .setWindowIcon = _glfwSetWindowIconAndroid, + .getWindowPos = _glfwGetWindowPosAndroid, + .setWindowPos = _glfwSetWindowPosAndroid, + .getWindowSize = _glfwGetWindowSizeAndroid, + .setWindowSize = _glfwSetWindowSizeAndroid, + .setWindowSizeLimits = _glfwSetWindowSizeLimitsAndroid, + .setWindowAspectRatio = _glfwSetWindowAspectRatioAndroid, + .getFramebufferSize = _glfwGetFramebufferSizeAndroid, + .getWindowFrameSize = _glfwGetWindowFrameSizeAndroid, + .getWindowContentScale = _glfwGetWindowContentScaleAndroid, + .iconifyWindow = _glfwIconifyWindowAndroid, + .restoreWindow = _glfwRestoreWindowAndroid, + .maximizeWindow = _glfwMaximizeWindowAndroid, + .showWindow = _glfwShowWindowAndroid, + .hideWindow = _glfwHideWindowAndroid, + .requestWindowAttention = _glfwRequestWindowAttentionAndroid, + .focusWindow = _glfwFocusWindowAndroid, + .setWindowMonitor = _glfwSetWindowMonitorAndroid, + .windowFocused = _glfwWindowFocusedAndroid, + .windowIconified = _glfwWindowIconifiedAndroid, + .windowVisible = _glfwWindowVisibleAndroid, + .windowMaximized = _glfwWindowMaximizedAndroid, + .windowHovered = _glfwWindowHoveredAndroid, + .framebufferTransparent = _glfwFramebufferTransparentAndroid, + .getWindowOpacity = _glfwGetWindowOpacityAndroid, + .setWindowResizable = _glfwSetWindowResizableAndroid, + .setWindowDecorated = _glfwSetWindowDecoratedAndroid, + .setWindowFloating = _glfwSetWindowFloatingAndroid, + .setWindowOpacity = _glfwSetWindowOpacityAndroid, + .setWindowMousePassthrough = _glfwSetWindowMousePassthroughAndroid, + .pollEvents = _glfwPollEventsAndroid, + .waitEvents = _glfwWaitEventsAndroid, + .waitEventsTimeout = _glfwWaitEventsTimeoutAndroid, + .postEmptyEvent = _glfwPostEmptyEventAndroid, + .getEGLPlatform = _glfwGetEGLPlatformAndroid, + .getEGLNativeDisplay = _glfwGetEGLNativeDisplayAndroid, + .getEGLNativeWindow = _glfwGetEGLNativeWindowAndroid, + .getRequiredInstanceExtensions = _glfwGetRequiredInstanceExtensionsAndroid, + .getPhysicalDevicePresentationSupport = _glfwGetPhysicalDevicePresentationSupportAndroid, + .createWindowSurface = _glfwCreateWindowSurfaceAndroid + }; + + *platform = android; + return GLFW_TRUE; +} + +int _glfwInitAndroid(void) +{ + _glfw.gstate.app = _globalAndroidApp; + _glfw.gstate.source = NULL; + + return GLFW_TRUE; +} + +void _glfwTerminateAndroid(void) +{ + _glfw.gstate.app = NULL; +} diff --git a/src/android_joystick.c b/src/android_joystick.c new file mode 100644 index 00000000..b3263417 --- /dev/null +++ b/src/android_joystick.c @@ -0,0 +1,56 @@ +//======================================================================== +// GLFW 3.5 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2024 kunitoki +// Copyright (c) 2017 Curi0 +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#include "internal.h" + + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +GLFWbool _glfwInitJoysticksAndroid(void) +{ + return GLFW_FALSE; +} + +void _glfwTerminateJoysticksAndroid(void) +{ +} + +GLFWbool _glfwPollJoystickAndroid(_GLFWjoystick* js, int mode) +{ + return GLFW_FALSE; +} + +const char* _glfwGetMappingNameAndroid(void) +{ + return "Android"; +} + +void _glfwUpdateGamepadGUIDAndroid(char* guid) +{ +} diff --git a/src/android_joystick.h b/src/android_joystick.h new file mode 100644 index 00000000..263a2ed8 --- /dev/null +++ b/src/android_joystick.h @@ -0,0 +1,35 @@ +//======================================================================== +// GLFW 3.5 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2024 kunitoki +// Copyright (c) 2017 Curi0 +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#define GLFW_ANDROID_JOYSTICK_STATE +#define GLFW_ANDROID_LIBRARY_JOYSTICK_STATE + +GLFWbool _glfwInitJoysticksAndroid(void); +void _glfwTerminateJoysticksAndroid(void); +GLFWbool _glfwPollJoystickAndroid(_GLFWjoystick* js, int mode); +const char* _glfwGetMappingNameAndroid(void); +void _glfwUpdateGamepadGUIDAndroid(char* guid); diff --git a/src/android_monitor.c b/src/android_monitor.c new file mode 100644 index 00000000..efb09944 --- /dev/null +++ b/src/android_monitor.c @@ -0,0 +1,82 @@ +//======================================================================== +// GLFW 3.5 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2024 kunitoki +// Copyright (c) 2017 Curi0 +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#include "internal.h" + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +void _glfwPollMonitorsAndroid(void) +{ +} + +void _glfwSetVideoModeAndroid(_GLFWmonitor* monitor, const GLFWvidmode* desired) +{ +} + +void _glfwRestoreVideoModeAndroid(_GLFWmonitor* monitor) +{ +} + +void _glfwFreeMonitorAndroid(_GLFWmonitor* monitor) +{ +} + +void _glfwGetMonitorPosAndroid(_GLFWmonitor* monitor, int* xpos, int* ypos) +{ +} + +void _glfwGetMonitorContentScaleAndroid(_GLFWmonitor* monitor, + float* xscale, float* yscale) +{ +} + +void _glfwGetMonitorWorkareaAndroid(_GLFWmonitor* monitor, + int* xpos, int* ypos, + int* width, int* height) +{ +} + +GLFWvidmode* _glfwGetVideoModesAndroid(_GLFWmonitor* monitor, int* count) +{ + return NULL; +} + +GLFWbool _glfwGetVideoModeAndroid(_GLFWmonitor* monitor, GLFWvidmode *mode) +{ + return GLFW_FALSE; +} + +GLFWbool _glfwGetGammaRampAndroid(_GLFWmonitor* monitor, GLFWgammaramp* ramp) +{ + return GLFW_FALSE; +} + +void _glfwSetGammaRampAndroid(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) +{ +} diff --git a/src/android_platform.h b/src/android_platform.h new file mode 100644 index 00000000..b2d79806 --- /dev/null +++ b/src/android_platform.h @@ -0,0 +1,134 @@ +//======================================================================== +// GLFW 3.5 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2024 kunitoki +// Copyright (c) 2017 Curi0 +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#include +#include +#include + +#define GLFW_ANDROID_WINDOW_STATE struct android_app* android; +#define GLFW_ANDROID_LIBRARY_WINDOW_STATE android_gstate gstate; +#define GLFW_ANDROID_MONITOR_STATE + +#define GLFW_ANDROID_CONTEXT_STATE +#define GLFW_ANDROID_CURSOR_STATE +#define GLFW_ANDROID_LIBRARY_CONTEXT_STATE + +#define GLFW_ANDROID_JOYSTICK_STATE +#define GLFW_ANDROID_LIBRARY_JOYSTICK_STATE + +typedef struct android_gstate +{ + struct android_app* app; + struct android_poll_source* source; +} android_gstate; + +typedef VkFlags VkAndroidSurfaceCreateFlagsKHR; + +typedef struct VkAndroidSurfaceCreateInfoKHR +{ + VkStructureType sType; + const void* pNext; + VkAndroidSurfaceCreateFlagsKHR flags; + ANativeWindow* window; +} VkAndroidSurfaceCreateInfoKHR; + +typedef VkResult (APIENTRY *PFN_vkCreateAndroidSurfaceKHR)(VkInstance, const VkAndroidSurfaceCreateInfoKHR*, const VkAllocationCallbacks*, VkSurfaceKHR*); + +GLFWbool _glfwConnectAndroid(int platformID, _GLFWplatform* platform); +int _glfwInitAndroid(void); +void _glfwTerminateAndroid(void); + +void _glfwFreeMonitorAndroid(_GLFWmonitor* monitor); +void _glfwGetMonitorPosAndroid(_GLFWmonitor* monitor, int* xpos, int* ypos); +void _glfwGetMonitorContentScaleAndroid(_GLFWmonitor* monitor, float* xscale, float* yscale); +void _glfwGetMonitorWorkareaAndroid(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height); +GLFWvidmode* _glfwGetVideoModesAndroid(_GLFWmonitor* monitor, int* found); +GLFWbool _glfwGetVideoModeAndroid(_GLFWmonitor* monitor, GLFWvidmode* mode); +GLFWbool _glfwGetGammaRampAndroid(_GLFWmonitor* monitor, GLFWgammaramp* ramp); +void _glfwSetGammaRampAndroid(_GLFWmonitor* monitor, const GLFWgammaramp* ramp); +void _glfwPollMonitorsAndroid(void); + +GLFWbool _glfwCreateWindowAndroid(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); +void _glfwDestroyWindowAndroid(_GLFWwindow* window); +void _glfwSetWindowTitleAndroid(_GLFWwindow* window, const char* title); +void _glfwSetWindowIconAndroid(_GLFWwindow* window, int count, const GLFWimage* images); +void _glfwSetWindowMonitorAndroid(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); +void _glfwGetWindowPosAndroid(_GLFWwindow* window, int* xpos, int* ypos); +void _glfwSetWindowPosAndroid(_GLFWwindow* window, int xpos, int ypos); +void _glfwGetWindowSizeAndroid(_GLFWwindow* window, int* width, int* height); +void _glfwSetWindowSizeAndroid(_GLFWwindow* window, int width, int height); +void _glfwSetWindowSizeLimitsAndroid(_GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); +void _glfwSetWindowAspectRatioAndroid(_GLFWwindow* window, int n, int d); +void _glfwGetFramebufferSizeAndroid(_GLFWwindow* window, int* width, int* height); +void _glfwGetWindowFrameSizeAndroid(_GLFWwindow* window, int* left, int* top, int* right, int* bottom); +void _glfwGetWindowContentScaleAndroid(_GLFWwindow* window, float* xscale, float* yscale); +void _glfwIconifyWindowAndroid(_GLFWwindow* window); +void _glfwRestoreWindowAndroid(_GLFWwindow* window); +void _glfwMaximizeWindowAndroid(_GLFWwindow* window); +GLFWbool _glfwWindowMaximizedAndroid(_GLFWwindow* window); +GLFWbool _glfwWindowHoveredAndroid(_GLFWwindow* window); +GLFWbool _glfwFramebufferTransparentAndroid(_GLFWwindow* window); +void _glfwSetWindowResizableAndroid(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowDecoratedAndroid(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowFloatingAndroid(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowMousePassthroughAndroid(_GLFWwindow* window, GLFWbool enabled); +float _glfwGetWindowOpacityAndroid(_GLFWwindow* window); +void _glfwSetWindowOpacityAndroid(_GLFWwindow* window, float opacity); +void _glfwSetRawMouseMotionAndroid(_GLFWwindow *window, GLFWbool enabled); +GLFWbool _glfwRawMouseMotionSupportedAndroid(void); +void _glfwShowWindowAndroid(_GLFWwindow* window); +void _glfwRequestWindowAttentionAndroid(_GLFWwindow* window); +void _glfwHideWindowAndroid(_GLFWwindow* window); +void _glfwFocusWindowAndroid(_GLFWwindow* window); +GLFWbool _glfwWindowFocusedAndroid(_GLFWwindow* window); +GLFWbool _glfwWindowIconifiedAndroid(_GLFWwindow* window); +GLFWbool _glfwWindowVisibleAndroid(_GLFWwindow* window); +void _glfwPollEventsAndroid(void); +void _glfwWaitEventsAndroid(void); +void _glfwWaitEventsTimeoutAndroid(double timeout); +void _glfwPostEmptyEventAndroid(void); +void _glfwGetCursorPosAndroid(_GLFWwindow* window, double* xpos, double* ypos); +void _glfwSetCursorPosAndroid(_GLFWwindow* window, double x, double y); +void _glfwSetCursorModeAndroid(_GLFWwindow* window, int mode); +GLFWbool _glfwCreateCursorAndroid(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot); +GLFWbool _glfwCreateStandardCursorAndroid(_GLFWcursor* cursor, int shape); +void _glfwDestroyCursorAndroid(_GLFWcursor* cursor); +void _glfwSetCursorAndroid(_GLFWwindow* window, _GLFWcursor* cursor); +void _glfwSetClipboardStringAndroid(const char* string); +const char* _glfwGetClipboardStringAndroid(void); +const char* _glfwGetScancodeNameAndroid(int scancode); +int _glfwGetKeyScancodeAndroid(int key); + +EGLenum _glfwGetEGLPlatformAndroid(EGLint** attribs); +EGLNativeDisplayType _glfwGetEGLNativeDisplayAndroid(void); +EGLNativeWindowType _glfwGetEGLNativeWindowAndroid(_GLFWwindow* window); + +void _glfwGetRequiredInstanceExtensionsAndroid(char** extensions); +GLFWbool _glfwGetPhysicalDevicePresentationSupportAndroid(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); +VkResult _glfwCreateWindowSurfaceAndroid(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +GLFWAPI struct android_app* glfwGetAndroidApp(GLFWwindow* handle); diff --git a/src/android_window.c b/src/android_window.c new file mode 100644 index 00000000..452225da --- /dev/null +++ b/src/android_window.c @@ -0,0 +1,563 @@ +//======================================================================== +// GLFW 3.5 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2024 kunitoki +// Copyright (c) 2017 Curi0 +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#include "internal.h" + +#include +#include +#include +#include +#include +#include + +#include + +static float lastCursorPosX = 0.0f; +static float lastCursorPosY = 0.0f; + +static void moveNativeWindowToBackground(ANativeActivity* nativeActivity) +{ + JNIEnv* env = NULL; + (*nativeActivity->vm)->AttachCurrentThread(nativeActivity->vm, &env, NULL); + + jmethodID moveTaskToBackMethod = (*env)->GetMethodID(env, nativeActivity->clazz, "moveTaskToBack", "(Z)Z"); + if (moveTaskToBackMethod == NULL) + return; + + (*env)->CallBooleanMethod(env, nativeActivity->clazz, moveTaskToBackMethod, JNI_TRUE); +} + +static int32_t handleInput(struct android_app* app, AInputEvent* event) +{ + if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) + { + size_t pointerCount = AMotionEvent_getPointerCount(event); + + for (size_t i = 0; i < pointerCount; ++i) + { + lastCursorPosX = AMotionEvent_getX(event, i); + lastCursorPosY = AMotionEvent_getY(event, i); + int32_t action = AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK; + + // Map Android touch events to GLFW touch events + switch (action) + { + case AMOTION_EVENT_ACTION_DOWN: + case AMOTION_EVENT_ACTION_POINTER_DOWN: + _glfwInputMouseClick(_glfw.windowListHead, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, 0); + break; + + case AMOTION_EVENT_ACTION_UP: + case AMOTION_EVENT_ACTION_POINTER_UP: + _glfwInputMouseClick(_glfw.windowListHead, GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE, 0); + break; + + case AMOTION_EVENT_ACTION_MOVE: + _glfwInputCursorPos(_glfw.windowListHead, lastCursorPosX, lastCursorPosY); + break; + + case AMOTION_EVENT_ACTION_CANCEL: + // Handle cancel if necessary + break; + } + } + + return 1; + } + else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) + { + _glfwInputKey(_glfw.windowListHead, 0 , AKeyEvent_getKeyCode(event), GLFW_PRESS, 0); + + return 1; + } + + return 0; +} + +static void handleEvents(int timeout) +{ + ALooper_pollOnce(timeout, NULL, NULL, (void**)&_glfw.gstate.source); + + if (_glfw.gstate.source != NULL) + _glfw.gstate.source->process(_glfw.gstate.app, _glfw.gstate.source); +} + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +GLFWbool _glfwCreateWindowAndroid(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig) +{ + // wait for window to become ready + while (_glfw.gstate.app->window == NULL) + handleEvents(-1); + + // hmmm maybe should be ANative_Window only? + window->android = _glfw.gstate.app; + window->android->onInputEvent = handleInput; + + if (ctxconfig->client != GLFW_NO_API) + { + if ((ctxconfig->source == GLFW_NATIVE_CONTEXT_API) | + (ctxconfig->source == GLFW_EGL_CONTEXT_API)) + { + if (!_glfwInitEGL()) + return GLFW_FALSE; + + if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) + return GLFW_FALSE; + } + else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API) + { + if (!_glfwInitOSMesa()) + return GLFW_FALSE; + + if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig)) + return GLFW_FALSE; + } + + if (!_glfwRefreshContextAttribs(window, ctxconfig)) + return GLFW_FALSE; + } + + return GLFW_TRUE; +} + +void _glfwDestroyWindowAndroid(_GLFWwindow* window) +{ + if (window->context.destroy) + window->context.destroy(window); + + ANativeActivity_finish(window->android->activity); +} + +void _glfwSetWindowTitleAndroid(_GLFWwindow* window, const char* title) +{ +} + +void _glfwSetWindowIconAndroid(_GLFWwindow* window, int count, + const GLFWimage* images) +{ +} + +void _glfwSetWindowMonitorAndroid(_GLFWwindow* window, + _GLFWmonitor* monitor, + int xpos, int ypos, + int width, int height, + int refreshRate) +{ +} + +void _glfwGetWindowPosAndroid(_GLFWwindow* window, int* xpos, int* ypos) +{ + if (xpos) + *xpos = 0; + + if (ypos) + *ypos = 0; +} + +void _glfwSetWindowPosAndroid(_GLFWwindow* window, int xpos, int ypos) +{ +} + +void _glfwGetWindowSizeAndroid(_GLFWwindow* window, int* width, int* height) +{ + if (width) + { + *width = (window->android->window != NULL) + ? ANativeWindow_getWidth(window->android->window) + : 0; + } + + if (height) + { + *height = (window->android->window != NULL) + ? ANativeWindow_getHeight(window->android->window) + : 0; + } +} + +void _glfwSetWindowSizeAndroid(_GLFWwindow* window, int width, int height) +{ +} + +void _glfwSetWindowSizeLimitsAndroid(_GLFWwindow* window, + int minwidth, int minheight, + int maxwidth, int maxheight) +{ +} + +void _glfwSetWindowAspectRatioAndroid(_GLFWwindow* window, int n, int d) +{ +} + +void _glfwGetFramebufferSizeAndroid(_GLFWwindow* window, int* width, int* height) +{ + // the underlying buffer geometry is currently being initialized from the window width and height... + // so high resolution displays are currently not supported...so it is safe to just call _glfwGetWindowSizeAndroid() for now + _glfwGetWindowSizeAndroid(window, width, height); +} + +void _glfwGetWindowFrameSizeAndroid(_GLFWwindow* window, + int* left, int* top, + int* right, int* bottom) +{ + if (left) + *left = window->android->contentRect.left; + + if (top) + *top = window->android->contentRect.top; + + if (right) + { + int windowWidth = (window->android->window != NULL) + ? ANativeWindow_getWidth(window->android->window) + : 0; + + int rightFrame = windowWidth - window->android->contentRect.right; + if (rightFrame < 0) rightFrame = 0; + + *right = rightFrame; + } + + if (bottom) + { + int windowHeight = (window->android->window != NULL) + ? ANativeWindow_getHeight(window->android->window) + : 0; + + int bottomFrame = windowHeight - window->android->contentRect.bottom; + if (bottomFrame < 0) bottomFrame = 0; + + *bottom = bottomFrame; + } +} + +void _glfwGetWindowContentScaleAndroid(_GLFWwindow* window, float* xscale, float* yscale) +{ + if (xscale) + { + int32_t widthDensity = AConfiguration_getScreenWidthDp(window->android->config); + if (widthDensity == ACONFIGURATION_SCREEN_WIDTH_DP_ANY) + { + *xscale = 1.0f; + } + else + { + int32_t widthPixels = ANativeWindow_getWidth(window->android->window); + *xscale = (float)widthPixels / (float)widthDensity; + } + } + + if (yscale) + { + int32_t heightDensity = AConfiguration_getScreenHeightDp(window->android->config); + if (heightDensity == ACONFIGURATION_SCREEN_HEIGHT_DP_ANY) + { + *yscale = 1.0f; + } + else + { + int32_t heightPixels = ANativeWindow_getHeight(window->android->window); + *yscale = (float)heightPixels / (float)heightDensity; + } + } +} + +void _glfwIconifyWindowAndroid(_GLFWwindow* window) +{ + moveNativeWindowToBackground(window->android->activity); +} + +void _glfwRestoreWindowAndroid(_GLFWwindow* window) +{ +} + +void _glfwMaximizeWindowAndroid(_GLFWwindow* window) +{ +} + +GLFWbool _glfwWindowMaximizedAndroid(_GLFWwindow* window) +{ + return GLFW_TRUE; +} + +GLFWbool _glfwWindowHoveredAndroid(_GLFWwindow* window) +{ + return GLFW_FALSE; +} + +GLFWbool _glfwFramebufferTransparentAndroid(_GLFWwindow* window) +{ + return GLFW_FALSE; +} + +void _glfwSetWindowResizableAndroid(_GLFWwindow* window, GLFWbool enabled) +{ +} + +void _glfwSetWindowDecoratedAndroid(_GLFWwindow* window, GLFWbool enabled) +{ +} + +void _glfwSetWindowFloatingAndroid(_GLFWwindow* window, GLFWbool enabled) +{ +} + +void _glfwSetWindowMousePassthroughAndroid(_GLFWwindow* window, GLFWbool enabled) +{ +} + +float _glfwGetWindowOpacityAndroid(_GLFWwindow* window) +{ + return 1.0f; +} + +void _glfwSetWindowOpacityAndroid(_GLFWwindow* window, float opacity) +{ +} + +void _glfwSetRawMouseMotionAndroid(_GLFWwindow *window, GLFWbool enabled) +{ +} + +GLFWbool _glfwRawMouseMotionSupportedAndroid(void) +{ + return GLFW_FALSE; +} + +void _glfwShowWindowAndroid(_GLFWwindow* window) +{ +} + +void _glfwRequestWindowAttentionAndroid(_GLFWwindow* window) +{ +} + +void _glfwHideWindowAndroid(_GLFWwindow* window) +{ +} + +void _glfwFocusWindowAndroid(_GLFWwindow* window) +{ +} + +GLFWbool _glfwWindowFocusedAndroid(_GLFWwindow* window) +{ + return GLFW_FALSE; +} + +GLFWbool _glfwWindowIconifiedAndroid(_GLFWwindow* window) +{ + return GLFW_FALSE; +} + +GLFWbool _glfwWindowVisibleAndroid(_GLFWwindow* window) +{ + return GLFW_FALSE; +} + +void _glfwPollEventsAndroid(void) +{ + handleEvents(0); +} + +void _glfwWaitEventsAndroid(void) +{ + handleEvents(-1); +} + +void _glfwWaitEventsTimeoutAndroid(double timeout) +{ + handleEvents(timeout * 1e3); +} + +void _glfwPostEmptyEventAndroid(void) +{ +} + +void _glfwGetCursorPosAndroid(_GLFWwindow* window, double* xpos, double* ypos) +{ + if (xpos) + *xpos = (double)lastCursorPosX; + + if (ypos) + *ypos = (double)lastCursorPosY; +} + +void _glfwSetCursorPosAndroid(_GLFWwindow* window, double x, double y) +{ +} + +void _glfwSetCursorModeAndroid(_GLFWwindow* window, int mode) +{ +} + +GLFWbool _glfwCreateCursorAndroid(_GLFWcursor* cursor, + const GLFWimage* image, + int xhot, int yhot) +{ + return GLFW_TRUE; +} + +GLFWbool _glfwCreateStandardCursorAndroid(_GLFWcursor* cursor, int shape) +{ + return GLFW_TRUE; +} + +void _glfwDestroyCursorAndroid(_GLFWcursor* cursor) +{ +} + +void _glfwSetCursorAndroid(_GLFWwindow* window, _GLFWcursor* cursor) +{ +} + +void _glfwSetClipboardStringAndroid(const char* string) +{ +} + +const char* _glfwGetClipboardStringAndroid(void) +{ + return NULL; +} + +const char* _glfwGetScancodeNameAndroid(int scancode) +{ + return ""; +} + +int _glfwGetKeyScancodeAndroid(int key) +{ + return -1; +} + +EGLenum _glfwGetEGLPlatformAndroid(EGLint** attribs) +{ + if (_glfw.egl.ANGLE_platform_angle) + { + int type = 0; + + if (_glfw.egl.ANGLE_platform_angle_opengl) + { + if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_OPENGL) + type = EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE; + else if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_OPENGLES) + type = EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE; + } + + if (_glfw.egl.ANGLE_platform_angle_vulkan) + { + if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_VULKAN) + type = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE; + } + + if (type) + { + *attribs = _glfw_calloc(3, sizeof(EGLint)); + (*attribs)[0] = EGL_PLATFORM_ANGLE_TYPE_ANGLE; + (*attribs)[1] = type; + (*attribs)[2] = EGL_NONE; + return EGL_PLATFORM_ANGLE_ANGLE; + } + } + + return 0; +} + +EGLNativeDisplayType _glfwGetEGLNativeDisplayAndroid(void) +{ + return EGL_DEFAULT_DISPLAY; +} + +EGLNativeWindowType _glfwGetEGLNativeWindowAndroid(_GLFWwindow* window) +{ + return ((EGLNativeWindowType) window->android->window); +} + +void _glfwGetRequiredInstanceExtensionsAndroid(char** extensions) +{ + if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_android_surface) + return; + + extensions[0] = "VK_KHR_surface"; + extensions[1] = "VK_KHR_android_surface"; +} + +GLFWbool _glfwGetPhysicalDevicePresentationSupportAndroid(VkInstance instance, + VkPhysicalDevice device, + uint32_t queuefamily) +{ + return GLFW_TRUE; +} + +VkResult _glfwCreateWindowSurfaceAndroid(VkInstance instance, + _GLFWwindow* window, + const VkAllocationCallbacks* allocator, + VkSurfaceKHR* surface) +{ + VkResult err; + VkAndroidSurfaceCreateInfoKHR sci; + PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; + + vkCreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR)vkGetInstanceProcAddr(instance, "vkCreateAndroidSurfaceKHR"); + if (!vkCreateAndroidSurfaceKHR) + { + _glfwInputError(GLFW_API_UNAVAILABLE, + "Android: Vulkan instance missing VK_KHR_android_surface extension"); + return VK_ERROR_EXTENSION_NOT_PRESENT; + } + + memset(&sci, 0, sizeof(sci)); + sci.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; + sci.window = window->android->window; + + err = vkCreateAndroidSurfaceKHR(instance, &sci, allocator, surface); + if (err) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Android: Failed to create Vulkan surface: %s", + _glfwGetVulkanResultString(err)); + } + + return err; +} + +////////////////////////////////////////////////////////////////////////// +////// GLFW native API ////// +////////////////////////////////////////////////////////////////////////// + +GLFWAPI struct android_app* glfwGetAndroidApp(GLFWwindow* handle) +{ + _GLFWwindow* window = (_GLFWwindow*)handle; + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + return window->android; +} diff --git a/src/egl_context.c b/src/egl_context.c index 517c64cb..79ee95e4 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -374,6 +374,8 @@ GLFWbool _glfwInitEGL(void) "EGL.dll", #elif defined(_GLFW_COCOA) "libEGL.dylib", +#elif defined(_GLFW_ANDROID) + "libEGL.so", #elif defined(__CYGWIN__) "libEGL-1.so", #elif defined(__OpenBSD__) || defined(__NetBSD__) @@ -773,6 +775,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, "libGLES_CM.dll", #elif defined(_GLFW_COCOA) "libGLESv1_CM.dylib", +#elif defined(_GLFW_ANDROID) + "libGLESv1_CM.so", + "libGLES_CM.so", #elif defined(__OpenBSD__) || defined(__NetBSD__) "libGLESv1_CM.so", #else @@ -790,6 +795,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, "libGLESv2.dll", #elif defined(_GLFW_COCOA) "libGLESv2.dylib", +#elif defined(_GLFW_ANDROID) + "libGLESv2.so", #elif defined(__CYGWIN__) "libGLESv2-2.so", #elif defined(__OpenBSD__) || defined(__NetBSD__) diff --git a/src/internal.h b/src/internal.h index 4f097aa8..0c9c9c0a 100644 --- a/src/internal.h +++ b/src/internal.h @@ -285,6 +285,7 @@ typedef enum VkStructureType VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000, VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000, VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000, + VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR = 1000008000, VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT = 1000256000, VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkStructureType; @@ -872,6 +873,7 @@ struct _GLFWlibrary GLFWbool KHR_xlib_surface; GLFWbool KHR_xcb_surface; GLFWbool KHR_wayland_surface; + GLFWbool KHR_android_surface; GLFWbool EXT_headless_surface; } vk; diff --git a/src/platform.c b/src/platform.c index 9ca64963..8d17fc54 100644 --- a/src/platform.c +++ b/src/platform.c @@ -56,6 +56,9 @@ static const struct #if defined(_GLFW_X11) { GLFW_PLATFORM_X11, _glfwConnectX11 }, #endif +#if defined(_GLFW_ANDROID) + { GLFW_PLATFORM_ANDROID, _glfwConnectAndroid }, +#endif }; GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform) @@ -68,6 +71,7 @@ GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform) desiredID != GLFW_PLATFORM_COCOA && desiredID != GLFW_PLATFORM_WAYLAND && desiredID != GLFW_PLATFORM_X11 && + desiredID != GLFW_PLATFORM_ANDROID && desiredID != GLFW_PLATFORM_NULL) { _glfwInputError(GLFW_INVALID_ENUM, "Invalid platform ID 0x%08X", desiredID); @@ -147,6 +151,7 @@ GLFWAPI int glfwPlatformSupported(int platformID) platformID != GLFW_PLATFORM_COCOA && platformID != GLFW_PLATFORM_WAYLAND && platformID != GLFW_PLATFORM_X11 && + platformID != GLFW_PLATFORM_ANDROID && platformID != GLFW_PLATFORM_NULL) { _glfwInputError(GLFW_INVALID_ENUM, "Invalid platform ID 0x%08X", platformID); @@ -181,6 +186,9 @@ GLFWAPI const char* glfwGetVersionString(void) #endif #if defined(_GLFW_X11) " X11 GLX" +#endif +#if defined(_GLFW_ANDROID) + " Android" #endif " Null" " EGL" @@ -209,4 +217,3 @@ GLFWAPI const char* glfwGetVersionString(void) #endif ; } - diff --git a/src/platform.h b/src/platform.h index 7ce4e015..c2e83083 100644 --- a/src/platform.h +++ b/src/platform.h @@ -90,6 +90,18 @@ #define GLFW_GLX_LIBRARY_CONTEXT_STATE #endif +#if defined(_GLFW_ANDROID) + #include "android_platform.h" + #define GLFW_EXPOSE_NATIVE_EGL +#else + #define GLFW_ANDROID_WINDOW_STATE + #define GLFW_ANDROID_MONITOR_STATE + #define GLFW_ANDROID_CURSOR_STATE + #define GLFW_ANDROID_LIBRARY_WINDOW_STATE + #define GLFW_ANDROID_CONTEXT_STATE + #define GLFW_ANDROID_LIBRARY_CONTEXT_STATE +#endif + #include "null_joystick.h" #if defined(_GLFW_WIN32) @@ -106,6 +118,13 @@ #define GLFW_COCOA_LIBRARY_JOYSTICK_STATE #endif +#if defined(_GLFW_ANDROID) + #include "android_joystick.h" +#else + #define GLFW_ANDROID_JOYSTICK_STATE + #define GLFW_ANDROID_LIBRARY_JOYSTICK_STATE +#endif + #if (defined(_GLFW_X11) || defined(_GLFW_WAYLAND)) && defined(__linux__) #define GLFW_BUILD_LINUX_JOYSTICK #endif @@ -122,6 +141,7 @@ GLFW_COCOA_WINDOW_STATE \ GLFW_WAYLAND_WINDOW_STATE \ GLFW_X11_WINDOW_STATE \ + GLFW_ANDROID_WINDOW_STATE \ GLFW_NULL_WINDOW_STATE \ #define GLFW_PLATFORM_MONITOR_STATE \ @@ -129,6 +149,7 @@ GLFW_COCOA_MONITOR_STATE \ GLFW_WAYLAND_MONITOR_STATE \ GLFW_X11_MONITOR_STATE \ + GLFW_ANDROID_MONITOR_STATE \ GLFW_NULL_MONITOR_STATE \ #define GLFW_PLATFORM_CURSOR_STATE \ @@ -136,11 +157,13 @@ GLFW_COCOA_CURSOR_STATE \ GLFW_WAYLAND_CURSOR_STATE \ GLFW_X11_CURSOR_STATE \ + GLFW_ANDROID_CURSOR_STATE \ GLFW_NULL_CURSOR_STATE \ #define GLFW_PLATFORM_JOYSTICK_STATE \ GLFW_WIN32_JOYSTICK_STATE \ GLFW_COCOA_JOYSTICK_STATE \ + GLFW_ANDROID_JOYSTICK_STATE \ GLFW_LINUX_JOYSTICK_STATE #define GLFW_PLATFORM_LIBRARY_WINDOW_STATE \ @@ -148,12 +171,14 @@ GLFW_COCOA_LIBRARY_WINDOW_STATE \ GLFW_WAYLAND_LIBRARY_WINDOW_STATE \ GLFW_X11_LIBRARY_WINDOW_STATE \ - GLFW_NULL_LIBRARY_WINDOW_STATE \ + GLFW_ANDROID_LIBRARY_WINDOW_STATE \ + GLFW_NULL_LIBRARY_WINDOW_STATE #define GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \ GLFW_WIN32_LIBRARY_JOYSTICK_STATE \ GLFW_COCOA_LIBRARY_JOYSTICK_STATE \ - GLFW_LINUX_LIBRARY_JOYSTICK_STATE + GLFW_LINUX_LIBRARY_JOYSTICK_STATE \ + GLFW_ANDROID_LIBRARY_JOYSTICK_STATE #define GLFW_PLATFORM_CONTEXT_STATE \ GLFW_WGL_CONTEXT_STATE \ diff --git a/src/vulkan.c b/src/vulkan.c index 9c87fcfe..9b061972 100644 --- a/src/vulkan.c +++ b/src/vulkan.c @@ -61,6 +61,8 @@ GLFWbool _glfwInitVulkan(int mode) _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib"); if (!_glfw.vk.handle) _glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa(); +#elif defined(_GLFW_ANDROID) + _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so"); #elif defined(__OpenBSD__) || defined(__NetBSD__) _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so"); #else @@ -142,6 +144,8 @@ GLFWbool _glfwInitVulkan(int mode) _glfw.vk.KHR_xcb_surface = GLFW_TRUE; else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0) _glfw.vk.KHR_wayland_surface = GLFW_TRUE; + else if (strcmp(ep[i].extensionName, "VK_KHR_android_surface") == 0) + _glfw.vk.KHR_android_surface = GLFW_TRUE; else if (strcmp(ep[i].extensionName, "VK_EXT_headless_surface") == 0) _glfw.vk.EXT_headless_surface = GLFW_TRUE; }