Path: blob/master/platform/android/display_server_android.cpp
11351 views
/**************************************************************************/1/* display_server_android.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "display_server_android.h"3132#include "java_godot_io_wrapper.h"33#include "java_godot_wrapper.h"34#include "os_android.h"35#include "tts_android.h"3637#include "core/config/project_settings.h"3839#if defined(RD_ENABLED)40#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"41#include "servers/rendering/rendering_device.h"4243#if defined(VULKAN_ENABLED)44#include "rendering_context_driver_vulkan_android.h"45#endif46#endif4748#ifdef GLES3_ENABLED49#include "drivers/gles3/rasterizer_gles3.h"5051#include <EGL/egl.h>52#endif5354DisplayServerAndroid *DisplayServerAndroid::get_singleton() {55return static_cast<DisplayServerAndroid *>(DisplayServer::get_singleton());56}5758bool DisplayServerAndroid::has_feature(Feature p_feature) const {59switch (p_feature) {60#ifndef DISABLE_DEPRECATED61case FEATURE_GLOBAL_MENU: {62return (native_menu && native_menu->has_feature(NativeMenu::FEATURE_GLOBAL_MENU));63} break;64#endif65case FEATURE_NATIVE_DIALOG_FILE: {66String sdk_version = OS::get_singleton()->get_version().get_slicec('.', 0);67return sdk_version.to_int() >= 29;68} break;6970case FEATURE_CURSOR_SHAPE:71//case FEATURE_CUSTOM_CURSOR_SHAPE:72//case FEATURE_HIDPI:73//case FEATURE_ICON:74//case FEATURE_IME:75case FEATURE_MOUSE:76//case FEATURE_MOUSE_WARP:77case FEATURE_NATIVE_DIALOG:78case FEATURE_NATIVE_DIALOG_INPUT:79//case FEATURE_NATIVE_DIALOG_FILE_EXTRA:80case FEATURE_NATIVE_DIALOG_FILE_MIME:81//case FEATURE_NATIVE_ICON:82case FEATURE_WINDOW_TRANSPARENCY:83case FEATURE_CLIPBOARD:84case FEATURE_KEEP_SCREEN_ON:85case FEATURE_ORIENTATION:86case FEATURE_TOUCHSCREEN:87case FEATURE_VIRTUAL_KEYBOARD:88case FEATURE_TEXT_TO_SPEECH:89return true;90default:91return false;92}93}9495String DisplayServerAndroid::get_name() const {96return "Android";97}9899bool DisplayServerAndroid::tts_is_speaking() const {100return TTS_Android::is_speaking();101}102103bool DisplayServerAndroid::tts_is_paused() const {104return TTS_Android::is_paused();105}106107TypedArray<Dictionary> DisplayServerAndroid::tts_get_voices() const {108return TTS_Android::get_voices();109}110111void DisplayServerAndroid::tts_speak(const String &p_text, const String &p_voice, int p_volume, float p_pitch, float p_rate, int p_utterance_id, bool p_interrupt) {112TTS_Android::speak(p_text, p_voice, p_volume, p_pitch, p_rate, p_utterance_id, p_interrupt);113}114115void DisplayServerAndroid::tts_pause() {116TTS_Android::pause();117}118119void DisplayServerAndroid::tts_resume() {120TTS_Android::resume();121}122123void DisplayServerAndroid::tts_stop() {124TTS_Android::stop();125}126127bool DisplayServerAndroid::is_dark_mode_supported() const {128GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();129ERR_FAIL_NULL_V(godot_java, false);130131return godot_java->is_dark_mode_supported();132}133134bool DisplayServerAndroid::is_dark_mode() const {135GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();136ERR_FAIL_NULL_V(godot_java, false);137138return godot_java->is_dark_mode();139}140141void DisplayServerAndroid::set_system_theme_change_callback(const Callable &p_callable) {142system_theme_changed = p_callable;143}144145void DisplayServerAndroid::emit_system_theme_changed() {146if (system_theme_changed.is_valid()) {147system_theme_changed.call_deferred();148}149}150151void DisplayServerAndroid::set_hardware_keyboard_connection_change_callback(const Callable &p_callable) {152hardware_keyboard_connection_changed = p_callable;153}154155void DisplayServerAndroid::emit_hardware_keyboard_connection_changed(bool p_connected) {156if (hardware_keyboard_connection_changed.is_valid()) {157hardware_keyboard_connection_changed.call_deferred(p_connected);158}159}160161void DisplayServerAndroid::clipboard_set(const String &p_text) {162GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();163ERR_FAIL_NULL(godot_java);164165if (godot_java->has_set_clipboard()) {166godot_java->set_clipboard(p_text);167} else {168DisplayServer::clipboard_set(p_text);169}170}171172String DisplayServerAndroid::clipboard_get() const {173GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();174ERR_FAIL_NULL_V(godot_java, String());175176if (godot_java->has_get_clipboard()) {177return godot_java->get_clipboard();178} else {179return DisplayServer::clipboard_get();180}181}182183bool DisplayServerAndroid::clipboard_has() const {184GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();185ERR_FAIL_NULL_V(godot_java, false);186187if (godot_java->has_has_clipboard()) {188return godot_java->has_clipboard();189} else {190return DisplayServer::clipboard_has();191}192}193194Error DisplayServerAndroid::dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) {195GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();196ERR_FAIL_NULL_V(godot_java, FAILED);197dialog_callback = p_callback;198return godot_java->show_dialog(p_title, p_description, p_buttons);199}200201void DisplayServerAndroid::emit_dialog_callback(int p_button_index) {202if (dialog_callback.is_valid()) {203dialog_callback.call_deferred(p_button_index);204}205}206207Error DisplayServerAndroid::dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) {208GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();209ERR_FAIL_NULL_V(godot_java, FAILED);210input_dialog_callback = p_callback;211return godot_java->show_input_dialog(p_title, p_description, p_partial);212}213214void DisplayServerAndroid::emit_input_dialog_callback(String p_text) {215if (input_dialog_callback.is_valid()) {216input_dialog_callback.call_deferred(p_text);217}218}219220Error DisplayServerAndroid::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback, WindowID p_window_id) {221GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();222ERR_FAIL_NULL_V(godot_java, FAILED);223file_picker_callback = p_callback;224return godot_java->show_file_picker(p_current_directory, p_filename, p_mode, p_filters);225}226227void DisplayServerAndroid::emit_file_picker_callback(bool p_ok, const Vector<String> &p_selected_paths) {228if (file_picker_callback.is_valid()) {229file_picker_callback.call_deferred(p_ok, p_selected_paths, 0);230}231}232233Color DisplayServerAndroid::get_accent_color() const {234GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();235ERR_FAIL_NULL_V(godot_java, Color(0, 0, 0, 0));236return godot_java->get_accent_color();237}238239Color DisplayServerAndroid::get_base_color() const {240GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();241ERR_FAIL_NULL_V(godot_java, Color(0, 0, 0, 0));242return godot_java->get_base_color();243}244245TypedArray<Rect2> DisplayServerAndroid::get_display_cutouts() const {246GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();247ERR_FAIL_NULL_V(godot_io_java, Array());248return godot_io_java->get_display_cutouts();249}250251Rect2i DisplayServerAndroid::get_display_safe_area() const {252GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();253ERR_FAIL_NULL_V(godot_io_java, Rect2i());254return godot_io_java->get_display_safe_area();255}256257void DisplayServerAndroid::screen_set_keep_on(bool p_enable) {258GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();259ERR_FAIL_NULL(godot_java);260261godot_java->set_keep_screen_on(p_enable);262keep_screen_on = p_enable;263}264265bool DisplayServerAndroid::screen_is_kept_on() const {266return keep_screen_on;267}268269void DisplayServerAndroid::screen_set_orientation(DisplayServer::ScreenOrientation p_orientation, int p_screen) {270p_screen = _get_screen_index(p_screen);271int screen_count = get_screen_count();272ERR_FAIL_INDEX(p_screen, screen_count);273274GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();275ERR_FAIL_NULL(godot_io_java);276277godot_io_java->set_screen_orientation(p_orientation);278}279280DisplayServer::ScreenOrientation DisplayServerAndroid::screen_get_orientation(int p_screen) const {281p_screen = _get_screen_index(p_screen);282int screen_count = get_screen_count();283ERR_FAIL_INDEX_V(p_screen, screen_count, SCREEN_LANDSCAPE);284285GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();286ERR_FAIL_NULL_V(godot_io_java, SCREEN_LANDSCAPE);287288const int orientation = godot_io_java->get_screen_orientation();289ERR_FAIL_INDEX_V_MSG(orientation, 7, SCREEN_LANDSCAPE, "Unrecognized screen orientation");290return (ScreenOrientation)orientation;291}292293int DisplayServerAndroid::get_display_rotation() const {294GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();295ERR_FAIL_NULL_V(godot_io_java, 0);296297return godot_io_java->get_display_rotation();298}299300int DisplayServerAndroid::get_screen_count() const {301return 1;302}303304int DisplayServerAndroid::get_primary_screen() const {305return 0;306}307308Point2i DisplayServerAndroid::screen_get_position(int p_screen) const {309p_screen = _get_screen_index(p_screen);310int screen_count = get_screen_count();311ERR_FAIL_INDEX_V(p_screen, screen_count, Point2i());312313return Point2i(0, 0);314}315316Size2i DisplayServerAndroid::screen_get_size(int p_screen) const {317p_screen = _get_screen_index(p_screen);318int screen_count = get_screen_count();319ERR_FAIL_INDEX_V(p_screen, screen_count, Size2i());320321return OS_Android::get_singleton()->get_display_size();322}323324Rect2i DisplayServerAndroid::screen_get_usable_rect(int p_screen) const {325p_screen = _get_screen_index(p_screen);326int screen_count = get_screen_count();327ERR_FAIL_INDEX_V(p_screen, screen_count, Rect2i());328329Size2i display_size = OS_Android::get_singleton()->get_display_size();330return Rect2i(0, 0, display_size.width, display_size.height);331}332333int DisplayServerAndroid::screen_get_dpi(int p_screen) const {334p_screen = _get_screen_index(p_screen);335int screen_count = get_screen_count();336ERR_FAIL_INDEX_V(p_screen, screen_count, 160);337338GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();339ERR_FAIL_NULL_V(godot_io_java, 160);340341return godot_io_java->get_screen_dpi();342}343344float DisplayServerAndroid::screen_get_scale(int p_screen) const {345p_screen = _get_screen_index(p_screen);346int screen_count = get_screen_count();347ERR_FAIL_INDEX_V(p_screen, screen_count, 1.0f);348349GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();350ERR_FAIL_NULL_V(godot_io_java, 1.0f);351352float screen_scale = godot_io_java->get_scaled_density();353354// Update the scale to avoid cropping.355Size2i screen_size = screen_get_size(p_screen);356if (screen_size != Size2i()) {357float width_scale = screen_size.width / (float)OS_Android::DEFAULT_WINDOW_WIDTH;358float height_scale = screen_size.height / (float)OS_Android::DEFAULT_WINDOW_HEIGHT;359screen_scale = MIN(screen_scale, MIN(width_scale, height_scale));360}361362return screen_scale;363}364365float DisplayServerAndroid::screen_get_refresh_rate(int p_screen) const {366p_screen = _get_screen_index(p_screen);367int screen_count = get_screen_count();368ERR_FAIL_INDEX_V(p_screen, screen_count, SCREEN_REFRESH_RATE_FALLBACK);369370GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();371if (!godot_io_java) {372ERR_PRINT("An error occurred while trying to get the screen refresh rate.");373return SCREEN_REFRESH_RATE_FALLBACK;374}375376return godot_io_java->get_screen_refresh_rate(SCREEN_REFRESH_RATE_FALLBACK);377}378379bool DisplayServerAndroid::is_touchscreen_available() const {380return true;381}382383void DisplayServerAndroid::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_length, int p_cursor_start, int p_cursor_end) {384GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();385ERR_FAIL_NULL(godot_io_java);386387if (godot_io_java->has_vk()) {388godot_io_java->show_vk(p_existing_text, (int)p_type, p_max_length, p_cursor_start, p_cursor_end);389} else {390ERR_PRINT("Virtual keyboard not available");391}392}393394void DisplayServerAndroid::virtual_keyboard_hide() {395GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();396ERR_FAIL_NULL(godot_io_java);397398if (godot_io_java->has_vk()) {399godot_io_java->hide_vk();400} else {401ERR_PRINT("Virtual keyboard not available");402}403}404405int DisplayServerAndroid::virtual_keyboard_get_height() const {406GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();407ERR_FAIL_NULL_V(godot_io_java, 0);408409return godot_io_java->get_vk_height();410}411412bool DisplayServerAndroid::has_hardware_keyboard() const {413GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();414ERR_FAIL_NULL_V(godot_io_java, false);415416return godot_io_java->has_hardware_keyboard();417}418419void DisplayServerAndroid::window_set_window_event_callback(const Callable &p_callable, DisplayServer::WindowID p_window) {420window_event_callback = p_callable;421}422423void DisplayServerAndroid::window_set_input_event_callback(const Callable &p_callable, DisplayServer::WindowID p_window) {424input_event_callback = p_callable;425}426427void DisplayServerAndroid::window_set_input_text_callback(const Callable &p_callable, DisplayServer::WindowID p_window) {428input_text_callback = p_callable;429}430431void DisplayServerAndroid::window_set_rect_changed_callback(const Callable &p_callable, DisplayServer::WindowID p_window) {432rect_changed_callback = p_callable;433}434435void DisplayServerAndroid::window_set_drop_files_callback(const Callable &p_callable, DisplayServer::WindowID p_window) {436// Not supported on Android.437}438439void DisplayServerAndroid::_window_callback(const Callable &p_callable, const Variant &p_arg, bool p_deferred) const {440if (p_callable.is_valid()) {441if (p_deferred) {442p_callable.call_deferred(p_arg);443} else {444p_callable.call(p_arg);445}446}447}448449void DisplayServerAndroid::send_window_event(DisplayServer::WindowEvent p_event, bool p_deferred) const {450_window_callback(window_event_callback, int(p_event), p_deferred);451}452453void DisplayServerAndroid::send_input_event(const Ref<InputEvent> &p_event) const {454_window_callback(input_event_callback, p_event);455}456457void DisplayServerAndroid::send_input_text(const String &p_text) const {458_window_callback(input_text_callback, p_text);459}460461void DisplayServerAndroid::_dispatch_input_events(const Ref<InputEvent> &p_event) {462DisplayServerAndroid::get_singleton()->send_input_event(p_event);463}464465Vector<DisplayServer::WindowID> DisplayServerAndroid::get_window_list() const {466Vector<WindowID> ret;467ret.push_back(MAIN_WINDOW_ID);468return ret;469}470471DisplayServer::WindowID DisplayServerAndroid::get_window_at_screen_position(const Point2i &p_position) const {472return MAIN_WINDOW_ID;473}474475int64_t DisplayServerAndroid::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const {476ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, 0);477switch (p_handle_type) {478case WINDOW_HANDLE: {479return reinterpret_cast<int64_t>(static_cast<OS_Android *>(OS::get_singleton())->get_godot_java()->get_activity());480}481case WINDOW_VIEW: {482return 0; // Not supported.483}484#ifdef GLES3_ENABLED485case DISPLAY_HANDLE: {486if (rendering_driver == "opengl3") {487return reinterpret_cast<int64_t>(eglGetCurrentDisplay());488}489return 0;490}491case OPENGL_CONTEXT: {492if (rendering_driver == "opengl3") {493return reinterpret_cast<int64_t>(eglGetCurrentContext());494}495return 0;496}497case EGL_DISPLAY: {498// @todo Find a way to get this from the Java side.499return 0;500}501case EGL_CONFIG: {502// @todo Find a way to get this from the Java side.503return 0;504}505#endif506default: {507return 0;508}509}510}511512void DisplayServerAndroid::window_attach_instance_id(ObjectID p_instance, DisplayServer::WindowID p_window) {513window_attached_instance_id = p_instance;514}515516ObjectID DisplayServerAndroid::window_get_attached_instance_id(DisplayServer::WindowID p_window) const {517return window_attached_instance_id;518}519520void DisplayServerAndroid::window_set_title(const String &p_title, DisplayServer::WindowID p_window) {521// Not supported on Android.522}523524int DisplayServerAndroid::window_get_current_screen(DisplayServer::WindowID p_window) const {525ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, INVALID_SCREEN);526return 0;527}528529void DisplayServerAndroid::window_set_current_screen(int p_screen, DisplayServer::WindowID p_window) {530// Not supported on Android.531}532533Point2i DisplayServerAndroid::window_get_position(DisplayServer::WindowID p_window) const {534return Point2i();535}536537Point2i DisplayServerAndroid::window_get_position_with_decorations(DisplayServer::WindowID p_window) const {538return Point2i();539}540541void DisplayServerAndroid::window_set_position(const Point2i &p_position, DisplayServer::WindowID p_window) {542// Not supported on Android.543}544545void DisplayServerAndroid::window_set_transient(DisplayServer::WindowID p_window, DisplayServer::WindowID p_parent) {546// Not supported on Android.547}548549void DisplayServerAndroid::window_set_max_size(const Size2i p_size, DisplayServer::WindowID p_window) {550// Not supported on Android.551}552553Size2i DisplayServerAndroid::window_get_max_size(DisplayServer::WindowID p_window) const {554return Size2i();555}556557void DisplayServerAndroid::window_set_min_size(const Size2i p_size, DisplayServer::WindowID p_window) {558// Not supported on Android.559}560561Size2i DisplayServerAndroid::window_get_min_size(DisplayServer::WindowID p_window) const {562return Size2i();563}564565void DisplayServerAndroid::window_set_size(const Size2i p_size, DisplayServer::WindowID p_window) {566// Not supported on Android.567}568569Size2i DisplayServerAndroid::window_get_size(DisplayServer::WindowID p_window) const {570return OS_Android::get_singleton()->get_display_size();571}572573Size2i DisplayServerAndroid::window_get_size_with_decorations(DisplayServer::WindowID p_window) const {574return OS_Android::get_singleton()->get_display_size();575}576577void DisplayServerAndroid::window_set_mode(DisplayServer::WindowMode p_mode, DisplayServer::WindowID p_window) {578OS_Android::get_singleton()->get_godot_java()->enable_immersive_mode(p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN);579}580581DisplayServer::WindowMode DisplayServerAndroid::window_get_mode(DisplayServer::WindowID p_window) const {582if (OS_Android::get_singleton()->get_godot_java()->is_in_immersive_mode()) {583return WINDOW_MODE_FULLSCREEN;584} else {585return WINDOW_MODE_MAXIMIZED;586}587}588589bool DisplayServerAndroid::window_is_maximize_allowed(DisplayServer::WindowID p_window) const {590return false;591}592593void DisplayServerAndroid::window_set_flag(DisplayServer::WindowFlags p_flag, bool p_enabled, DisplayServer::WindowID p_window) {594// Not supported on Android.595}596597bool DisplayServerAndroid::window_get_flag(DisplayServer::WindowFlags p_flag, DisplayServer::WindowID p_window) const {598ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, false);599switch (p_flag) {600case WindowFlags::WINDOW_FLAG_TRANSPARENT:601return is_window_transparency_available();602603default:604return false;605}606}607608void DisplayServerAndroid::window_request_attention(DisplayServer::WindowID p_window) {609// Not supported on Android.610}611612void DisplayServerAndroid::window_move_to_foreground(DisplayServer::WindowID p_window) {613// Not supported on Android.614}615616bool DisplayServerAndroid::window_is_focused(WindowID p_window) const {617return true;618}619620bool DisplayServerAndroid::window_can_draw(DisplayServer::WindowID p_window) const {621return true;622}623624bool DisplayServerAndroid::can_any_window_draw() const {625return true;626}627628void DisplayServerAndroid::window_set_color(const Color &p_color) {629GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();630ERR_FAIL_NULL(godot_java);631godot_java->set_window_color(p_color);632}633634void DisplayServerAndroid::process_events() {635Input::get_singleton()->flush_buffered_events();636}637638Vector<String> DisplayServerAndroid::get_rendering_drivers_func() {639Vector<String> drivers;640641#ifdef GLES3_ENABLED642drivers.push_back("opengl3");643#endif644#ifdef VULKAN_ENABLED645drivers.push_back("vulkan");646#endif647648return drivers;649}650651DisplayServer *DisplayServerAndroid::create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error) {652DisplayServer *ds = memnew(DisplayServerAndroid(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, p_context, p_parent_window, r_error));653if (r_error != OK) {654if (p_rendering_driver == "vulkan") {655OS::get_singleton()->alert(656"Your device seems not to support the required Vulkan version.\n\n"657"Please try exporting your game using the 'gl_compatibility' renderer.",658"Unable to initialize Vulkan video driver");659} else {660OS::get_singleton()->alert(661"Your device seems not to support the required OpenGL ES 3.0 version.",662"Unable to initialize OpenGL video driver");663}664}665return ds;666}667668void DisplayServerAndroid::register_android_driver() {669register_create_function("android", create_func, get_rendering_drivers_func);670}671672void DisplayServerAndroid::reset_window() {673#if defined(RD_ENABLED)674if (rendering_context) {675if (rendering_device) {676rendering_device->screen_free(MAIN_WINDOW_ID);677}678679VSyncMode last_vsync_mode = rendering_context->window_get_vsync_mode(MAIN_WINDOW_ID);680rendering_context->window_destroy(MAIN_WINDOW_ID);681682union {683#ifdef VULKAN_ENABLED684RenderingContextDriverVulkanAndroid::WindowPlatformData vulkan;685#endif686} wpd;687#ifdef VULKAN_ENABLED688if (rendering_driver == "vulkan") {689ANativeWindow *native_window = OS_Android::get_singleton()->get_native_window();690ERR_FAIL_NULL(native_window);691wpd.vulkan.window = native_window;692}693#endif694695if (rendering_context->window_create(MAIN_WINDOW_ID, &wpd) != OK) {696ERR_PRINT(vformat("Failed to reset %s window.", rendering_driver));697memdelete(rendering_context);698rendering_context = nullptr;699return;700}701702Size2i display_size = OS_Android::get_singleton()->get_display_size();703rendering_context->window_set_size(MAIN_WINDOW_ID, display_size.width, display_size.height);704rendering_context->window_set_vsync_mode(MAIN_WINDOW_ID, last_vsync_mode);705706if (rendering_device) {707rendering_device->screen_create(MAIN_WINDOW_ID);708}709}710#endif711}712713void DisplayServerAndroid::notify_surface_changed(int p_width, int p_height) {714if (rect_changed_callback.is_valid()) {715rect_changed_callback.call(Rect2i(0, 0, p_width, p_height));716}717}718719DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error) {720rendering_driver = p_rendering_driver;721722keep_screen_on = GLOBAL_GET("display/window/energy_saving/keep_screen_on");723724native_menu = memnew(NativeMenu);725726#if defined(RD_ENABLED)727rendering_context = nullptr;728rendering_device = nullptr;729730#if defined(VULKAN_ENABLED)731if (rendering_driver == "vulkan") {732rendering_context = memnew(RenderingContextDriverVulkanAndroid);733}734#endif735736if (rendering_context) {737if (rendering_context->initialize() != OK) {738memdelete(rendering_context);739rendering_context = nullptr;740#if defined(GLES3_ENABLED)741bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3");742if (fallback_to_opengl3 && rendering_driver != "opengl3") {743WARN_PRINT("Your device does not seem to support Vulkan, switching to OpenGL 3.");744rendering_driver = "opengl3";745OS::get_singleton()->set_current_rendering_method("gl_compatibility");746OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);747} else748#endif749{750ERR_PRINT(vformat("Failed to initialize %s context", rendering_driver));751r_error = ERR_UNAVAILABLE;752return;753}754}755}756757if (rendering_context) {758union {759#ifdef VULKAN_ENABLED760RenderingContextDriverVulkanAndroid::WindowPlatformData vulkan;761#endif762} wpd;763#ifdef VULKAN_ENABLED764if (rendering_driver == "vulkan") {765ANativeWindow *native_window = OS_Android::get_singleton()->get_native_window();766ERR_FAIL_NULL(native_window);767wpd.vulkan.window = native_window;768}769#endif770771if (rendering_context->window_create(MAIN_WINDOW_ID, &wpd) != OK) {772ERR_PRINT(vformat("Failed to create %s window.", rendering_driver));773memdelete(rendering_context);774rendering_context = nullptr;775r_error = ERR_UNAVAILABLE;776return;777}778779Size2i display_size = OS_Android::get_singleton()->get_display_size();780rendering_context->window_set_size(MAIN_WINDOW_ID, display_size.width, display_size.height);781rendering_context->window_set_vsync_mode(MAIN_WINDOW_ID, p_vsync_mode);782783rendering_device = memnew(RenderingDevice);784if (rendering_device->initialize(rendering_context, MAIN_WINDOW_ID) != OK) {785rendering_device = nullptr;786memdelete(rendering_context);787rendering_context = nullptr;788r_error = ERR_UNAVAILABLE;789return;790}791rendering_device->screen_create(MAIN_WINDOW_ID);792793RendererCompositorRD::make_current();794}795#endif796797#if defined(GLES3_ENABLED)798if (rendering_driver == "opengl3") {799RasterizerGLES3::make_current(false);800}801#endif802803Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);804805r_error = OK;806}807808DisplayServerAndroid::~DisplayServerAndroid() {809if (native_menu) {810memdelete(native_menu);811native_menu = nullptr;812}813814#if defined(RD_ENABLED)815if (rendering_device) {816memdelete(rendering_device);817}818if (rendering_context) {819memdelete(rendering_context);820}821#endif822}823824void DisplayServerAndroid::process_accelerometer(const Vector3 &p_accelerometer) {825Input::get_singleton()->set_accelerometer(p_accelerometer);826}827828void DisplayServerAndroid::process_gravity(const Vector3 &p_gravity) {829Input::get_singleton()->set_gravity(p_gravity);830}831832void DisplayServerAndroid::process_magnetometer(const Vector3 &p_magnetometer) {833Input::get_singleton()->set_magnetometer(p_magnetometer);834}835836void DisplayServerAndroid::process_gyroscope(const Vector3 &p_gyroscope) {837Input::get_singleton()->set_gyroscope(p_gyroscope);838}839840void DisplayServerAndroid::_mouse_update_mode() {841MouseMode wanted_mouse_mode = mouse_mode_override_enabled842? mouse_mode_override843: mouse_mode_base;844845if (!OS_Android::get_singleton()->get_godot_java()->get_godot_view()->can_update_pointer_icon() || !OS_Android::get_singleton()->get_godot_java()->get_godot_view()->can_capture_pointer()) {846return;847}848if (mouse_mode == wanted_mouse_mode) {849return;850}851852if (wanted_mouse_mode == MouseMode::MOUSE_MODE_HIDDEN) {853OS_Android::get_singleton()->get_godot_java()->get_godot_view()->set_pointer_icon(CURSOR_TYPE_NULL);854} else {855cursor_set_shape(cursor_shape);856}857858if (wanted_mouse_mode == MouseMode::MOUSE_MODE_CAPTURED) {859OS_Android::get_singleton()->get_godot_java()->get_godot_view()->request_pointer_capture();860} else {861OS_Android::get_singleton()->get_godot_java()->get_godot_view()->release_pointer_capture();862}863864mouse_mode = wanted_mouse_mode;865}866867void DisplayServerAndroid::mouse_set_mode(MouseMode p_mode) {868ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX);869if (p_mode == mouse_mode_base) {870return;871}872mouse_mode_base = p_mode;873_mouse_update_mode();874}875876DisplayServer::MouseMode DisplayServerAndroid::mouse_get_mode() const {877return mouse_mode;878}879880void DisplayServerAndroid::mouse_set_mode_override(MouseMode p_mode) {881ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX);882if (p_mode == mouse_mode_override) {883return;884}885mouse_mode_override = p_mode;886_mouse_update_mode();887}888889DisplayServer::MouseMode DisplayServerAndroid::mouse_get_mode_override() const {890return mouse_mode_override;891}892893void DisplayServerAndroid::mouse_set_mode_override_enabled(bool p_override_enabled) {894mouse_mode_override_enabled = p_override_enabled;895_mouse_update_mode();896}897898bool DisplayServerAndroid::mouse_is_mode_override_enabled() const {899return mouse_mode_override_enabled;900}901902Point2i DisplayServerAndroid::mouse_get_position() const {903return Input::get_singleton()->get_mouse_position();904}905906BitField<MouseButtonMask> DisplayServerAndroid::mouse_get_button_state() const {907return Input::get_singleton()->get_mouse_button_mask();908}909910void DisplayServerAndroid::_cursor_set_shape_helper(CursorShape p_shape, bool force) {911if (!OS_Android::get_singleton()->get_godot_java()->get_godot_view()->can_update_pointer_icon()) {912return;913}914if (cursor_shape == p_shape && !force) {915return;916}917918cursor_shape = p_shape;919920if (mouse_mode == MouseMode::MOUSE_MODE_VISIBLE || mouse_mode == MouseMode::MOUSE_MODE_CONFINED) {921OS_Android::get_singleton()->get_godot_java()->get_godot_view()->set_pointer_icon(android_cursors[cursor_shape]);922}923}924925void DisplayServerAndroid::cursor_set_shape(DisplayServer::CursorShape p_shape) {926ERR_FAIL_INDEX(p_shape, CURSOR_MAX);927_cursor_set_shape_helper(p_shape);928}929930DisplayServer::CursorShape DisplayServerAndroid::cursor_get_shape() const {931return cursor_shape;932}933934void DisplayServerAndroid::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {935ERR_FAIL_INDEX(p_shape, CURSOR_MAX);936String cursor_path = p_cursor.is_valid() ? p_cursor->get_path() : "";937if (!cursor_path.is_empty()) {938cursor_path = ProjectSettings::get_singleton()->globalize_path(cursor_path);939}940OS_Android::get_singleton()->get_godot_java()->get_godot_view()->configure_pointer_icon(android_cursors[cursor_shape], cursor_path, p_hotspot);941_cursor_set_shape_helper(p_shape, true);942}943944void DisplayServerAndroid::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {945#if defined(RD_ENABLED)946if (rendering_context) {947rendering_context->window_set_vsync_mode(p_window, p_vsync_mode);948}949#endif950}951952DisplayServer::VSyncMode DisplayServerAndroid::window_get_vsync_mode(WindowID p_window) const {953#if defined(RD_ENABLED)954if (rendering_context) {955return rendering_context->window_get_vsync_mode(p_window);956}957#endif958return DisplayServer::VSYNC_ENABLED;959}960961void DisplayServerAndroid::reset_swap_buffers_flag() {962swap_buffers_flag = false;963}964965bool DisplayServerAndroid::should_swap_buffers() const {966return swap_buffers_flag;967}968969void DisplayServerAndroid::swap_buffers() {970swap_buffers_flag = true;971}972973void DisplayServerAndroid::set_native_icon(const String &p_filename) {974// NOT SUPPORTED975}976977void DisplayServerAndroid::set_icon(const Ref<Image> &p_icon) {978// NOT SUPPORTED979}980981bool DisplayServerAndroid::is_window_transparency_available() const {982return GLOBAL_GET_CACHED(bool, "display/window/per_pixel_transparency/allowed");983}984985986