Browse Source

Vulkan rendering for Android

PouleyKetchoupp 5 years ago
parent
commit
af424b1c7c
28 changed files with 499 additions and 187 deletions
  1. 1 0
      .gitignore
  2. 6 1
      drivers/vulkan/SCsub
  3. 6 3
      drivers/vulkan/rendering_device_vulkan.cpp
  4. 2 2
      drivers/vulkan/vulkan_context.h
  5. 1 1
      platform/android/SCsub
  6. 4 4
      platform/android/detect.py
  7. 1 1
      platform/android/java/lib/AndroidManifest.xml
  8. 1 0
      platform/android/java/lib/build.gradle
  9. 33 26
      platform/android/java/lib/src/org/godotengine/godot/Godot.java
  10. 30 9
      platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
  11. 4 3
      platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
  12. 15 14
      platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
  13. 1 1
      platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java
  14. 142 0
      platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
  15. 16 16
      platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
  16. 6 6
      platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java
  17. 21 21
      platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
  18. 11 11
      platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
  19. 30 13
      platform/android/java/lib/src/org/godotengine/godot/vulkan/VkRenderer.kt
  20. 3 3
      platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt
  21. 2 2
      platform/android/java/lib/src/org/godotengine/godot/vulkan/VkThread.kt
  22. 0 1
      platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java
  23. 8 3
      platform/android/java_godot_lib_jni.cpp
  24. 1 1
      platform/android/java_godot_lib_jni.h
  25. 58 19
      platform/android/os_android.cpp
  26. 15 4
      platform/android/os_android.h
  27. 68 0
      platform/android/vulkan/vulkan_context_android.cpp
  28. 13 22
      platform/android/vulkan/vulkan_context_android.h

+ 1 - 0
.gitignore

@@ -21,6 +21,7 @@ project.properties
 platform/android/java/lib/.cxx/
 platform/android/java/lib/.cxx/
 platform/android/java/libs/*
 platform/android/java/libs/*
 platform/android/java/app/libs/*
 platform/android/java/app/libs/*
+platform/android/java/lib/.cxx/*
 
 
 # General c++ generated files
 # General c++ generated files
 *.lib
 *.lib

+ 6 - 1
drivers/vulkan/SCsub

@@ -4,7 +4,12 @@ Import("env")
 
 
 env.add_source_files(env.drivers_sources, "*.cpp")
 env.add_source_files(env.drivers_sources, "*.cpp")
 
 
-if env["builtin_vulkan"]:
+if env["platform"] == "android":
+    # Use NDK Vulkan headers
+    thirdparty_dir = env["ANDROID_NDK_ROOT"] + "/sources/third_party/vulkan/src"
+    thirdparty_includes = [thirdparty_dir, thirdparty_dir + "/include", thirdparty_dir + "/layers", thirdparty_dir + "/layers/generated"]
+    env.Prepend(CPPPATH=thirdparty_includes)
+elif env["builtin_vulkan"]:
     # Use bundled Vulkan headers
     # Use bundled Vulkan headers
     thirdparty_dir = "#thirdparty/vulkan"
     thirdparty_dir = "#thirdparty/vulkan"
     env.Prepend(CPPPATH=[thirdparty_dir, thirdparty_dir + "/include", thirdparty_dir + "/loader"])
     env.Prepend(CPPPATH=[thirdparty_dir, thirdparty_dir + "/include", thirdparty_dir + "/loader"])

+ 6 - 3
drivers/vulkan/rendering_device_vulkan.cpp

@@ -1564,15 +1564,17 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
 	image_create_info.pNext = nullptr;
 	image_create_info.pNext = nullptr;
 	image_create_info.flags = 0;
 	image_create_info.flags = 0;
 
 
-	VkImageFormatListCreateInfoKHR format_list_create_info;
-	Vector<VkFormat> allowed_formats;
-
+	// TODO: vkCreateImage fails with format list on Android (VK_ERROR_OUT_OF_HOST_MEMORY)
+#ifndef ANDROID_ENABLED
 	if (p_format.shareable_formats.size()) {
 	if (p_format.shareable_formats.size()) {
 		image_create_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
 		image_create_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
+
+		Vector<VkFormat> allowed_formats;
 		for (int i = 0; i < p_format.shareable_formats.size(); i++) {
 		for (int i = 0; i < p_format.shareable_formats.size(); i++) {
 			allowed_formats.push_back(vulkan_formats[p_format.shareable_formats[i]]);
 			allowed_formats.push_back(vulkan_formats[p_format.shareable_formats[i]]);
 		}
 		}
 
 
+		VkImageFormatListCreateInfoKHR format_list_create_info;
 		format_list_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR;
 		format_list_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR;
 		format_list_create_info.pNext = nullptr;
 		format_list_create_info.pNext = nullptr;
 		format_list_create_info.viewFormatCount = allowed_formats.size();
 		format_list_create_info.viewFormatCount = allowed_formats.size();
@@ -1584,6 +1586,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
 		ERR_FAIL_COND_V_MSG(p_view.format_override != DATA_FORMAT_MAX && p_format.shareable_formats.find(p_view.format_override) == -1, RID(),
 		ERR_FAIL_COND_V_MSG(p_view.format_override != DATA_FORMAT_MAX && p_format.shareable_formats.find(p_view.format_override) == -1, RID(),
 				"If supplied a list of shareable formats, the current view format override must be present in the list");
 				"If supplied a list of shareable formats, the current view format override must be present in the list");
 	}
 	}
+#endif
 	if (p_format.type == TEXTURE_TYPE_CUBE || p_format.type == TEXTURE_TYPE_CUBE_ARRAY) {
 	if (p_format.type == TEXTURE_TYPE_CUBE || p_format.type == TEXTURE_TYPE_CUBE_ARRAY) {
 		image_create_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
 		image_create_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
 	}
 	}

+ 2 - 2
drivers/vulkan/vulkan_context.h

@@ -45,8 +45,6 @@ class VulkanContext {
 		FRAME_LAG = 2
 		FRAME_LAG = 2
 	};
 	};
 
 
-	bool use_validation_layers;
-
 	VkInstance inst;
 	VkInstance inst;
 	VkSurfaceKHR surface;
 	VkSurfaceKHR surface;
 	VkPhysicalDevice gpu;
 	VkPhysicalDevice gpu;
@@ -181,6 +179,8 @@ protected:
 
 
 	bool buffers_prepared;
 	bool buffers_prepared;
 
 
+	bool use_validation_layers;
+
 public:
 public:
 	VkDevice get_device();
 	VkDevice get_device();
 	VkPhysicalDevice get_physical_device();
 	VkPhysicalDevice get_physical_device();

+ 1 - 1
platform/android/SCsub

@@ -17,8 +17,8 @@ android_files = [
     "java_godot_io_wrapper.cpp",
     "java_godot_io_wrapper.cpp",
     "jni_utils.cpp",
     "jni_utils.cpp",
     "android_keys_utils.cpp",
     "android_keys_utils.cpp",
-    "vulkan/vk_renderer_jni.cpp",
     "plugin/godot_plugin_jni.cpp",
     "plugin/godot_plugin_jni.cpp",
+    "vulkan/vulkan_context_android.cpp"
 ]
 ]
 
 
 env_android = env.Clone()
 env_android = env.Clone()

+ 4 - 4
platform/android/detect.py

@@ -25,7 +25,7 @@ def get_opts():
 
 
     return [
     return [
         ("ANDROID_NDK_ROOT", "Path to the Android NDK", os.environ.get("ANDROID_NDK_ROOT", 0)),
         ("ANDROID_NDK_ROOT", "Path to the Android NDK", os.environ.get("ANDROID_NDK_ROOT", 0)),
-        ("ndk_platform", 'Target platform (android-<api>, e.g. "android-18")', "android-18"),
+        ("ndk_platform", 'Target platform (android-<api>, e.g. "android-24")', "android-24"),
         EnumVariable("android_arch", "Target architecture", "armv7", ("armv7", "arm64v8", "x86", "x86_64")),
         EnumVariable("android_arch", "Target architecture", "armv7", ("armv7", "arm64v8", "x86", "x86_64")),
         BoolVariable("android_neon", "Enable NEON support (armv7 only)", True),
         BoolVariable("android_neon", "Enable NEON support (armv7 only)", True),
     ]
     ]
@@ -102,7 +102,7 @@ def configure(env):
     neon_text = ""
     neon_text = ""
     if env["android_arch"] == "armv7" and env["android_neon"]:
     if env["android_arch"] == "armv7" and env["android_neon"]:
         neon_text = " (with NEON)"
         neon_text = " (with NEON)"
-    print("Building for Android (" + env["android_arch"] + ")" + neon_text)
+    print("Building for Android, platform " + env["ndk_platform"] + " (" + env["android_arch"] + ")" + neon_text)
 
 
     can_vectorize = True
     can_vectorize = True
     if env["android_arch"] == "x86":
     if env["android_arch"] == "x86":
@@ -314,8 +314,8 @@ def configure(env):
     )
     )
 
 
     env.Prepend(CPPPATH=["#platform/android"])
     env.Prepend(CPPPATH=["#platform/android"])
-    env.Append(CPPDEFINES=["ANDROID_ENABLED", "UNIX_ENABLED", "NO_FCNTL"])
-    env.Append(LIBS=["OpenSLES", "EGL", "GLESv3", "GLESv2", "android", "log", "z", "dl"])
+    env.Append(CPPDEFINES=["ANDROID_ENABLED", "UNIX_ENABLED", "VULKAN_ENABLED", "NO_FCNTL"])
+    env.Append(LIBS=["OpenSLES", "EGL", "GLESv2", "vulkan", "android", "log", "z", "dl"])
 
 
 
 
 # Return NDK version string in source.properties (adapted from the Chromium project).
 # Return NDK version string in source.properties (adapted from the Chromium project).

+ 1 - 1
platform/android/java/lib/AndroidManifest.xml

@@ -13,7 +13,7 @@
     <instrumentation
     <instrumentation
         android:icon="@mipmap/icon"
         android:icon="@mipmap/icon"
         android:label="@string/godot_project_name_string"
         android:label="@string/godot_project_name_string"
-        android:name=".GodotInstrumentation"
+        android:name="org.godotengine.godot.GodotInstrumentation"
         android:targetPackage="org.godotengine.godot" />
         android:targetPackage="org.godotengine.godot" />
 
 
 </manifest>
 </manifest>

+ 1 - 0
platform/android/java/lib/build.gradle

@@ -1,4 +1,5 @@
 apply plugin: 'com.android.library'
 apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
 
 
 dependencies {
 dependencies {
     implementation libraries.supportCoreUtils
     implementation libraries.supportCoreUtils

+ 33 - 26
platform/android/java/lib/src/org/godotengine/godot/Godot.java

@@ -153,7 +153,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 	private String[] command_line;
 	private String[] command_line;
 	private boolean use_apk_expansion;
 	private boolean use_apk_expansion;
 
 
-	public GodotView mView;
+	public GodotRenderView mRenderView;
 	private boolean godot_initialized = false;
 	private boolean godot_initialized = false;
 
 
 	private SensorManager mSensorManager;
 	private SensorManager mSensorManager;
@@ -213,34 +213,41 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 		setContentView(layout);
 		setContentView(layout);
 
 
 		// GodotEditText layout
 		// GodotEditText layout
-		GodotEditText edittext = new GodotEditText(this);
-		edittext.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+		GodotEditText editText = new GodotEditText(this);
+		editText.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
 		// ...add to FrameLayout
 		// ...add to FrameLayout
-		layout.addView(edittext);
+		layout.addView(editText);
 
 
-		mView = new GodotView(this, xrMode, use_32_bits, use_debug_opengl);
-		layout.addView(mView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
-		edittext.setView(mView);
-		io.setEdit(edittext);
+		GodotLib.setup(command_line);
 
 
-		mView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+		final String videoDriver = GodotLib.getGlobal("rendering/quality/driver/driver_name");
+		if (videoDriver.equals("Vulkan")) {
+			mRenderView = new GodotVulkanRenderView(this);
+		} else {
+			mRenderView = new GodotGLRenderView(this, xrMode, use_32_bits, use_debug_opengl);
+		}
+
+		View view = mRenderView.getView();
+		layout.addView(view, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+		editText.setView(mRenderView);
+		io.setEdit(editText);
+
+		view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
 			@Override
 			@Override
 			public void onGlobalLayout() {
 			public void onGlobalLayout() {
 				Point fullSize = new Point();
 				Point fullSize = new Point();
 				getWindowManager().getDefaultDisplay().getSize(fullSize);
 				getWindowManager().getDefaultDisplay().getSize(fullSize);
 				Rect gameSize = new Rect();
 				Rect gameSize = new Rect();
-				mView.getWindowVisibleDisplayFrame(gameSize);
+				mRenderView.getView().getWindowVisibleDisplayFrame(gameSize);
 
 
 				final int keyboardHeight = fullSize.y - gameSize.bottom;
 				final int keyboardHeight = fullSize.y - gameSize.bottom;
 				GodotLib.setVirtualKeyboardHeight(keyboardHeight);
 				GodotLib.setVirtualKeyboardHeight(keyboardHeight);
 			}
 			}
 		});
 		});
 
 
-		final String[] current_command_line = command_line;
-		mView.queueEvent(new Runnable() {
+		mRenderView.queueOnRenderThread(new Runnable() {
 			@Override
 			@Override
 			public void run() {
 			public void run() {
-				GodotLib.setup(current_command_line);
 
 
 				// Must occur after GodotLib.setup has completed.
 				// Must occur after GodotLib.setup has completed.
 				for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
 				for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
@@ -384,7 +391,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 	 */
 	 */
 	@Keep
 	@Keep
 	private Surface getSurface() {
 	private Surface getSurface() {
-		return mView.getHolder().getSurface();
+		return mRenderView.getView().getHolder().getSurface();
 	}
 	}
 
 
 	/**
 	/**
@@ -617,7 +624,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 			}
 			}
 			return;
 			return;
 		}
 		}
-		mView.onPause();
+		mRenderView.onActivityPaused();
 
 
 		mSensorManager.unregisterListener(this);
 		mSensorManager.unregisterListener(this);
 
 
@@ -655,7 +662,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 			return;
 			return;
 		}
 		}
 
 
-		mView.onResume();
+		mRenderView.onActivityResumed();
 
 
 		mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
 		mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
 		mSensorManager.registerListener(this, mGravity, SensorManager.SENSOR_DELAY_GAME);
 		mSensorManager.registerListener(this, mGravity, SensorManager.SENSOR_DELAY_GAME);
@@ -721,8 +728,8 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 		final float z = adjustedValues[2];
 		final float z = adjustedValues[2];
 
 
 		final int typeOfSensor = event.sensor.getType();
 		final int typeOfSensor = event.sensor.getType();
-		if (mView != null) {
-			mView.queueEvent(new Runnable() {
+		if (mRenderView != null) {
+			mRenderView.queueOnRenderThread(new Runnable() {
 				@Override
 				@Override
 				public void run() {
 				public void run() {
 					if (typeOfSensor == Sensor.TYPE_ACCELEROMETER) {
 					if (typeOfSensor == Sensor.TYPE_ACCELEROMETER) {
@@ -773,8 +780,8 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 			}
 			}
 		}
 		}
 
 
-		if (shouldQuit && mView != null) {
-			mView.queueEvent(new Runnable() {
+		if (shouldQuit && mRenderView != null) {
+			mRenderView.queueOnRenderThread(new Runnable() {
 				@Override
 				@Override
 				public void run() {
 				public void run() {
 					GodotLib.back();
 					GodotLib.back();
@@ -789,8 +796,8 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 	 * This must be called after the render thread has started.
 	 * This must be called after the render thread has started.
 	 */
 	 */
 	public final void runOnRenderThread(@NonNull Runnable action) {
 	public final void runOnRenderThread(@NonNull Runnable action) {
-		if (mView != null) {
-			mView.queueEvent(action);
+		if (mRenderView != null) {
+			mRenderView.queueOnRenderThread(action);
 		}
 		}
 	}
 	}
 
 
@@ -847,7 +854,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 		if (evcount == 0)
 		if (evcount == 0)
 			return true;
 			return true;
 
 
-		if (mView != null) {
+		if (mRenderView != null) {
 			final int[] arr = new int[event.getPointerCount() * 3];
 			final int[] arr = new int[event.getPointerCount() * 3];
 
 
 			for (int i = 0; i < event.getPointerCount(); i++) {
 			for (int i = 0; i < event.getPointerCount(); i++) {
@@ -860,7 +867,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 
 
 			//System.out.printf("gaction: %d\n",event.getAction());
 			//System.out.printf("gaction: %d\n",event.getAction());
 			final int action = event.getAction() & MotionEvent.ACTION_MASK;
 			final int action = event.getAction() & MotionEvent.ACTION_MASK;
-			mView.queueEvent(new Runnable() {
+			mRenderView.queueOnRenderThread(new Runnable() {
 				@Override
 				@Override
 				public void run() {
 				public void run() {
 					switch (action) {
 					switch (action) {
@@ -911,7 +918,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 		for (int i = cc.length; --i >= 0; cnt += cc[i] != 0 ? 1 : 0)
 		for (int i = cc.length; --i >= 0; cnt += cc[i] != 0 ? 1 : 0)
 			;
 			;
 		if (cnt == 0) return super.onKeyMultiple(inKeyCode, repeatCount, event);
 		if (cnt == 0) return super.onKeyMultiple(inKeyCode, repeatCount, event);
-		mView.queueEvent(new Runnable() {
+		mRenderView.queueOnRenderThread(new Runnable() {
 			// This method will be called on the rendering thread:
 			// This method will be called on the rendering thread:
 			public void run() {
 			public void run() {
 				for (int i = 0, n = cc.length; i < n; i++) {
 				for (int i = 0, n = cc.length; i < n; i++) {
@@ -1033,6 +1040,6 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 				progress.mOverallTotal));
 				progress.mOverallTotal));
 	}
 	}
 	public void initInputDevices() {
 	public void initInputDevices() {
-		mView.initInputDevices();
+		mRenderView.initInputDevices();
 	}
 	}
 }
 }

+ 30 - 9
platform/android/java/lib/src/org/godotengine/godot/GodotView.java → platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java

@@ -1,5 +1,5 @@
 /*************************************************************************/
 /*************************************************************************/
-/*  GodotView.java                                                       */
+/*  GodotGLRenderView.java                                               */
 /*************************************************************************/
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
 /*                           GODOT ENGINE                                */
@@ -35,6 +35,7 @@ import android.opengl.GLSurfaceView;
 import android.view.GestureDetector;
 import android.view.GestureDetector;
 import android.view.KeyEvent;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.MotionEvent;
+import android.view.SurfaceView;
 import org.godotengine.godot.input.GodotGestureHandler;
 import org.godotengine.godot.input.GodotGestureHandler;
 import org.godotengine.godot.input.GodotInputHandler;
 import org.godotengine.godot.input.GodotInputHandler;
 import org.godotengine.godot.utils.GLUtils;
 import org.godotengine.godot.utils.GLUtils;
@@ -64,16 +65,14 @@ import org.godotengine.godot.xr.regular.RegularFallbackConfigChooser;
  *   that matches it exactly (with regards to red/green/blue/alpha channels
  *   that matches it exactly (with regards to red/green/blue/alpha channels
  *   bit depths). Failure to do so would result in an EGL_BAD_MATCH error.
  *   bit depths). Failure to do so would result in an EGL_BAD_MATCH error.
  */
  */
-public class GodotView extends GLSurfaceView {
-
-	private static String TAG = GodotView.class.getSimpleName();
+public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView {
 
 
 	private final Godot activity;
 	private final Godot activity;
 	private final GodotInputHandler inputHandler;
 	private final GodotInputHandler inputHandler;
 	private final GestureDetector detector;
 	private final GestureDetector detector;
 	private final GodotRenderer godotRenderer;
 	private final GodotRenderer godotRenderer;
 
 
-	public GodotView(Godot activity, XRMode xrMode, boolean p_use_32_bits, boolean p_use_debug_opengl) {
+	public GodotGLRenderView(Godot activity, XRMode xrMode, boolean p_use_32_bits, boolean p_use_debug_opengl) {
 		super(activity);
 		super(activity);
 		GLUtils.use_32 = p_use_32_bits;
 		GLUtils.use_32 = p_use_32_bits;
 		GLUtils.use_debug_opengl = p_use_debug_opengl;
 		GLUtils.use_debug_opengl = p_use_debug_opengl;
@@ -85,10 +84,36 @@ public class GodotView extends GLSurfaceView {
 		init(xrMode, false, 16, 0);
 		init(xrMode, false, 16, 0);
 	}
 	}
 
 
+	@Override
+	public SurfaceView getView() {
+		return this;
+	}
+
+	@Override
 	public void initInputDevices() {
 	public void initInputDevices() {
 		this.inputHandler.initInputDevices();
 		this.inputHandler.initInputDevices();
 	}
 	}
 
 
+	@Override
+	public void queueOnRenderThread(Runnable event) {
+		queueEvent(event);
+	}
+
+	@Override
+	public void onActivityPaused() {
+		onPause();
+	}
+
+	@Override
+	public void onActivityResumed() {
+		onResume();
+	}
+
+	@Override
+	public void onBackPressed() {
+		activity.onBackPressed();
+	}
+
 	@SuppressLint("ClickableViewAccessibility")
 	@SuppressLint("ClickableViewAccessibility")
 	@Override
 	@Override
 	public boolean onTouchEvent(MotionEvent event) {
 	public boolean onTouchEvent(MotionEvent event) {
@@ -170,10 +195,6 @@ public class GodotView extends GLSurfaceView {
 		setRenderer(godotRenderer);
 		setRenderer(godotRenderer);
 	}
 	}
 
 
-	public void onBackPressed() {
-		activity.onBackPressed();
-	}
-
 	@Override
 	@Override
 	public void onResume() {
 	public void onResume() {
 		super.onResume();
 		super.onResume();

+ 4 - 3
platform/android/java/lib/src/org/godotengine/godot/GodotLib.java

@@ -32,6 +32,7 @@ package org.godotengine.godot;
 
 
 import android.app.Activity;
 import android.app.Activity;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEvent;
+import android.view.Surface;
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 import javax.microedition.khronos.opengles.GL10;
 
 
@@ -72,11 +73,11 @@ public class GodotLib {
 	public static native void resize(int width, int height);
 	public static native void resize(int width, int height);
 
 
 	/**
 	/**
-	 * Invoked on the GL thread when the underlying Android surface is created or recreated.
+	 * Invoked on the render thread when the underlying Android surface is created or recreated.
+	 * @param p_surface
 	 * @param p_32_bits
 	 * @param p_32_bits
-	 * @see android.opengl.GLSurfaceView.Renderer#onSurfaceCreated(GL10, EGLConfig)
 	 */
 	 */
-	public static native void newcontext(boolean p_32_bits);
+	public static native void newcontext(Surface p_surface, boolean p_32_bits);
 
 
 	/**
 	/**
 	 * Forward {@link Activity#onBackPressed()} event from the main thread to the GL thread.
 	 * Forward {@link Activity#onBackPressed()} event from the main thread to the GL thread.

+ 15 - 14
platform/android/vulkan/vk_renderer_jni.h → platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java

@@ -1,5 +1,5 @@
 /*************************************************************************/
 /*************************************************************************/
-/*  vk_renderer_jni.h                                                    */
+/*  GodotRenderView.java                                                 */
 /*************************************************************************/
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
 /*                           GODOT ENGINE                                */
@@ -28,19 +28,20 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 /*************************************************************************/
 
 
-#ifndef VK_RENDERER_JNI_H
-#define VK_RENDERER_JNI_H
+package org.godotengine.godot;
 
 
-#include <android/log.h>
-#include <jni.h>
+import android.view.SurfaceView;
 
 
-extern "C" {
-JNIEXPORT void JNICALL Java_org_godotengine_godot_vulkan_VkRenderer_nativeOnVkSurfaceCreated(JNIEnv *env, jobject obj, jobject j_surface);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_vulkan_VkRenderer_nativeOnVkSurfaceChanged(JNIEnv *env, jobject object, jobject j_surface, jint width, jint height);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_vulkan_VkRenderer_nativeOnVkResume(JNIEnv *env, jobject obj);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_vulkan_VkRenderer_nativeOnVkDrawFrame(JNIEnv *env, jobject obj);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_vulkan_VkRenderer_nativeOnVkPause(JNIEnv *env, jobject obj);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_vulkan_VkRenderer_nativeOnVkDestroy(JNIEnv *env, jobject obj);
-}
+public interface GodotRenderView {
+
+	abstract public SurfaceView getView();
+
+	abstract public void initInputDevices();
 
 
-#endif // VK_RENDERER_JNI_H
+	abstract public void queueOnRenderThread(Runnable event);
+
+	abstract public void onActivityPaused();
+	abstract public void onActivityResumed();
+
+	abstract public void onBackPressed();
+}

+ 1 - 1
platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java

@@ -70,7 +70,7 @@ class GodotRenderer implements GLSurfaceView.Renderer {
 	}
 	}
 
 
 	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
 	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
-		GodotLib.newcontext(GLUtils.use_32);
+		GodotLib.newcontext(null, GLUtils.use_32);
 		for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
 		for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
 			plugin.onGLSurfaceCreated(gl, config);
 			plugin.onGLSurfaceCreated(gl, config);
 		}
 		}

+ 142 - 0
platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java

@@ -0,0 +1,142 @@
+/*************************************************************************/
+/*  GodotVulkanRenderView.java                                           */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+package org.godotengine.godot;
+
+import android.annotation.SuppressLint;
+import android.view.GestureDetector;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.SurfaceView;
+import org.godotengine.godot.input.GodotGestureHandler;
+import org.godotengine.godot.input.GodotInputHandler;
+import org.godotengine.godot.vulkan.VkRenderer;
+import org.godotengine.godot.vulkan.VkSurfaceView;
+
+public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderView {
+
+	private final Godot mActivity;
+	private final GodotInputHandler mInputHandler;
+	private final GestureDetector mGestureDetector;
+	private final VkRenderer mRenderer;
+
+	public GodotVulkanRenderView(Godot activity) {
+		super(activity);
+
+		mActivity = activity;
+		mInputHandler = new GodotInputHandler(this);
+		mGestureDetector = new GestureDetector(mActivity, new GodotGestureHandler(this));
+		mRenderer = new VkRenderer();
+
+		setFocusableInTouchMode(true);
+		startRenderer(mRenderer);
+	}
+
+	@Override
+	public SurfaceView getView() {
+		return this;
+	}
+
+	@Override
+	public void initInputDevices() {
+		mInputHandler.initInputDevices();
+	}
+
+	@Override
+	public void queueOnRenderThread(Runnable event) {
+		queueOnVkThread(event);
+	}
+
+	@Override
+	public void onActivityPaused() {
+		onPause();
+	}
+
+	@Override
+	public void onActivityResumed() {
+		onResume();
+	}
+
+	@Override
+	public void onBackPressed() {
+		mActivity.onBackPressed();
+	}
+
+	@SuppressLint("ClickableViewAccessibility")
+	@Override
+	public boolean onTouchEvent(MotionEvent event) {
+		super.onTouchEvent(event);
+		mGestureDetector.onTouchEvent(event);
+		return mActivity.gotTouchEvent(event);
+	}
+
+	@Override
+	public boolean onKeyUp(final int keyCode, KeyEvent event) {
+		return mInputHandler.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event);
+	}
+
+	@Override
+	public boolean onKeyDown(final int keyCode, KeyEvent event) {
+		return mInputHandler.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
+	}
+
+	@Override
+	public boolean onGenericMotionEvent(MotionEvent event) {
+		return mInputHandler.onGenericMotionEvent(event) || super.onGenericMotionEvent(event);
+	}
+
+	@Override
+	public void onResume() {
+		super.onResume();
+
+		queueOnVkThread(new Runnable() {
+			@Override
+			public void run() {
+				// Resume the renderer
+				mRenderer.onVkResume();
+				GodotLib.focusin();
+			}
+		});
+	}
+
+	@Override
+	public void onPause() {
+		super.onPause();
+
+		queueOnVkThread(new Runnable() {
+			@Override
+			public void run() {
+				GodotLib.focusout();
+				// Pause the renderer
+				mRenderer.onVkPause();
+			}
+		});
+	}
+}

+ 16 - 16
platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java

@@ -51,7 +51,7 @@ public class GodotEditText extends EditText {
 	// ===========================================================
 	// ===========================================================
 	// Fields
 	// Fields
 	// ===========================================================
 	// ===========================================================
-	private GodotView mView;
+	private GodotRenderView mRenderView;
 	private GodotTextInputWrapper mInputWrapper;
 	private GodotTextInputWrapper mInputWrapper;
 	private EditHandler sHandler = new EditHandler(this);
 	private EditHandler sHandler = new EditHandler(this);
 	private String mOriginText;
 	private String mOriginText;
@@ -76,22 +76,22 @@ public class GodotEditText extends EditText {
 	// ===========================================================
 	// ===========================================================
 	public GodotEditText(final Context context) {
 	public GodotEditText(final Context context) {
 		super(context);
 		super(context);
-		this.initView();
+		initView();
 	}
 	}
 
 
 	public GodotEditText(final Context context, final AttributeSet attrs) {
 	public GodotEditText(final Context context, final AttributeSet attrs) {
 		super(context, attrs);
 		super(context, attrs);
-		this.initView();
+		initView();
 	}
 	}
 
 
 	public GodotEditText(final Context context, final AttributeSet attrs, final int defStyle) {
 	public GodotEditText(final Context context, final AttributeSet attrs, final int defStyle) {
 		super(context, attrs, defStyle);
 		super(context, attrs, defStyle);
-		this.initView();
+		initView();
 	}
 	}
 
 
 	protected void initView() {
 	protected void initView() {
-		this.setPadding(0, 0, 0, 0);
-		this.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
+		setPadding(0, 0, 0, 0);
+		setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
 	}
 	}
 
 
 	private void handleMessage(final Message msg) {
 	private void handleMessage(final Message msg) {
@@ -106,7 +106,7 @@ public class GodotEditText extends EditText {
 					edit.mInputWrapper.setOriginText(text);
 					edit.mInputWrapper.setOriginText(text);
 					edit.addTextChangedListener(edit.mInputWrapper);
 					edit.addTextChangedListener(edit.mInputWrapper);
 					setMaxInputLength(edit, msg.arg1);
 					setMaxInputLength(edit, msg.arg1);
-					final InputMethodManager imm = (InputMethodManager)mView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+					final InputMethodManager imm = (InputMethodManager)mRenderView.getView().getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
 					imm.showSoftInput(edit, 0);
 					imm.showSoftInput(edit, 0);
 				}
 				}
 			} break;
 			} break;
@@ -115,9 +115,9 @@ public class GodotEditText extends EditText {
 				GodotEditText edit = (GodotEditText)msg.obj;
 				GodotEditText edit = (GodotEditText)msg.obj;
 
 
 				edit.removeTextChangedListener(mInputWrapper);
 				edit.removeTextChangedListener(mInputWrapper);
-				final InputMethodManager imm = (InputMethodManager)mView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+				final InputMethodManager imm = (InputMethodManager)mRenderView.getView().getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
 				imm.hideSoftInputFromWindow(edit.getWindowToken(), 0);
 				imm.hideSoftInputFromWindow(edit.getWindowToken(), 0);
-				edit.mView.requestFocus();
+				edit.mRenderView.getView().requestFocus();
 			} break;
 			} break;
 		}
 		}
 	}
 	}
@@ -135,12 +135,12 @@ public class GodotEditText extends EditText {
 	// ===========================================================
 	// ===========================================================
 	// Getter & Setter
 	// Getter & Setter
 	// ===========================================================
 	// ===========================================================
-	public void setView(final GodotView view) {
-		this.mView = view;
+	public void setView(final GodotRenderView view) {
+		mRenderView = view;
 		if (mInputWrapper == null)
 		if (mInputWrapper == null)
-			mInputWrapper = new GodotTextInputWrapper(mView, this);
-		this.setOnEditorActionListener(mInputWrapper);
-		view.requestFocus();
+			mInputWrapper = new GodotTextInputWrapper(mRenderView, this);
+		setOnEditorActionListener(mInputWrapper);
+		view.getView().requestFocus();
 	}
 	}
 
 
 	// ===========================================================
 	// ===========================================================
@@ -152,7 +152,7 @@ public class GodotEditText extends EditText {
 
 
 		/* Let GlSurfaceView get focus if back key is input. */
 		/* Let GlSurfaceView get focus if back key is input. */
 		if (keyCode == KeyEvent.KEYCODE_BACK) {
 		if (keyCode == KeyEvent.KEYCODE_BACK) {
-			this.mView.requestFocus();
+			mRenderView.getView().requestFocus();
 		}
 		}
 
 
 		return true;
 		return true;
@@ -162,7 +162,7 @@ public class GodotEditText extends EditText {
 	// Methods
 	// Methods
 	// ===========================================================
 	// ===========================================================
 	public void showKeyboard(String p_existing_text, int p_max_input_length) {
 	public void showKeyboard(String p_existing_text, int p_max_input_length) {
-		this.mOriginText = p_existing_text;
+		mOriginText = p_existing_text;
 
 
 		final Message msg = new Message();
 		final Message msg = new Message();
 		msg.what = HANDLER_OPEN_IME_KEYBOARD;
 		msg.what = HANDLER_OPEN_IME_KEYBOARD;

+ 6 - 6
platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java

@@ -34,22 +34,22 @@ import android.util.Log;
 import android.view.GestureDetector;
 import android.view.GestureDetector;
 import android.view.MotionEvent;
 import android.view.MotionEvent;
 import org.godotengine.godot.GodotLib;
 import org.godotengine.godot.GodotLib;
-import org.godotengine.godot.GodotView;
+import org.godotengine.godot.GodotRenderView;
 
 
 /**
 /**
- * Handles gesture input related events for the {@link GodotView} view.
+ * Handles gesture input related events for the {@link GodotRenderView} view.
  * https://developer.android.com/reference/android/view/GestureDetector.SimpleOnGestureListener
  * https://developer.android.com/reference/android/view/GestureDetector.SimpleOnGestureListener
  */
  */
 public class GodotGestureHandler extends GestureDetector.SimpleOnGestureListener {
 public class GodotGestureHandler extends GestureDetector.SimpleOnGestureListener {
 
 
-	private final GodotView godotView;
+	private final GodotRenderView mRenderView;
 
 
-	public GodotGestureHandler(GodotView godotView) {
-		this.godotView = godotView;
+	public GodotGestureHandler(GodotRenderView godotView) {
+		mRenderView = godotView;
 	}
 	}
 
 
 	private void queueEvent(Runnable task) {
 	private void queueEvent(Runnable task) {
-		godotView.queueEvent(task);
+		mRenderView.queueOnRenderThread(task);
 	}
 	}
 
 
 	@Override
 	@Override

+ 21 - 21
platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java

@@ -42,27 +42,27 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.Comparator;
 import java.util.List;
 import java.util.List;
 import org.godotengine.godot.GodotLib;
 import org.godotengine.godot.GodotLib;
-import org.godotengine.godot.GodotView;
+import org.godotengine.godot.GodotRenderView;
 import org.godotengine.godot.input.InputManagerCompat.InputDeviceListener;
 import org.godotengine.godot.input.InputManagerCompat.InputDeviceListener;
 
 
 /**
 /**
- * Handles input related events for the {@link GodotView} view.
+ * Handles input related events for the {@link GodotRenderView} view.
  */
  */
 public class GodotInputHandler implements InputDeviceListener {
 public class GodotInputHandler implements InputDeviceListener {
 
 
-	private final ArrayList<Joystick> joysticksDevices = new ArrayList<Joystick>();
+	private final ArrayList<Joystick> mJoysticksDevices = new ArrayList<Joystick>();
 
 
-	private final GodotView godotView;
-	private final InputManagerCompat inputManager;
+	private final GodotRenderView mRenderView;
+	private final InputManagerCompat mInputManager;
 
 
-	public GodotInputHandler(GodotView godotView) {
-		this.godotView = godotView;
-		this.inputManager = InputManagerCompat.Factory.getInputManager(godotView.getContext());
-		this.inputManager.registerInputDeviceListener(this, null);
+	public GodotInputHandler(GodotRenderView godotView) {
+		mRenderView = godotView;
+		mInputManager = InputManagerCompat.Factory.getInputManager(mRenderView.getView().getContext());
+		mInputManager.registerInputDeviceListener(this, null);
 	}
 	}
 
 
 	private void queueEvent(Runnable task) {
 	private void queueEvent(Runnable task) {
-		godotView.queueEvent(task);
+		mRenderView.queueOnRenderThread(task);
 	}
 	}
 
 
 	private boolean isKeyEvent_GameDevice(int source) {
 	private boolean isKeyEvent_GameDevice(int source) {
@@ -113,7 +113,7 @@ public class GodotInputHandler implements InputDeviceListener {
 
 
 	public boolean onKeyDown(final int keyCode, KeyEvent event) {
 	public boolean onKeyDown(final int keyCode, KeyEvent event) {
 		if (keyCode == KeyEvent.KEYCODE_BACK) {
 		if (keyCode == KeyEvent.KEYCODE_BACK) {
-			godotView.onBackPressed();
+			mRenderView.onBackPressed();
 			// press 'back' button should not terminate program
 			// press 'back' button should not terminate program
 			//normal handle 'back' event in game logic
 			//normal handle 'back' event in game logic
 			return true;
 			return true;
@@ -164,7 +164,7 @@ public class GodotInputHandler implements InputDeviceListener {
 
 
 			// Check if the device exists
 			// Check if the device exists
 			if (device_id > -1) {
 			if (device_id > -1) {
-				Joystick joy = joysticksDevices.get(device_id);
+				Joystick joy = mJoysticksDevices.get(device_id);
 
 
 				for (int i = 0; i < joy.axes.size(); i++) {
 				for (int i = 0; i < joy.axes.size(); i++) {
 					InputDevice.MotionRange range = joy.axes.get(i);
 					InputDevice.MotionRange range = joy.axes.get(i);
@@ -208,11 +208,11 @@ public class GodotInputHandler implements InputDeviceListener {
 
 
 	public void initInputDevices() {
 	public void initInputDevices() {
 		/* initially add input devices*/
 		/* initially add input devices*/
-		int[] deviceIds = inputManager.getInputDeviceIds();
+		int[] deviceIds = mInputManager.getInputDeviceIds();
 		for (int deviceId : deviceIds) {
 		for (int deviceId : deviceIds) {
-			InputDevice device = inputManager.getInputDevice(deviceId);
+			InputDevice device = mInputManager.getInputDevice(deviceId);
 			if (DEBUG) {
 			if (DEBUG) {
-				Log.v("GodotView", String.format("init() deviceId:%d, Name:%s\n", deviceId, device.getName()));
+				Log.v("GodotInputHandler", String.format("init() deviceId:%d, Name:%s\n", deviceId, device.getName()));
 			}
 			}
 			onInputDeviceAdded(deviceId);
 			onInputDeviceAdded(deviceId);
 		}
 		}
@@ -224,13 +224,13 @@ public class GodotInputHandler implements InputDeviceListener {
 
 
 		// Check if the device has not been already added
 		// Check if the device has not been already added
 		if (id < 0) {
 		if (id < 0) {
-			InputDevice device = inputManager.getInputDevice(deviceId);
+			InputDevice device = mInputManager.getInputDevice(deviceId);
 			//device can be null if deviceId is not found
 			//device can be null if deviceId is not found
 			if (device != null) {
 			if (device != null) {
 				int sources = device.getSources();
 				int sources = device.getSources();
 				if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) ||
 				if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) ||
 						((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK)) {
 						((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK)) {
-					id = joysticksDevices.size();
+					id = mJoysticksDevices.size();
 
 
 					Joystick joy = new Joystick();
 					Joystick joy = new Joystick();
 					joy.device_id = deviceId;
 					joy.device_id = deviceId;
@@ -249,7 +249,7 @@ public class GodotInputHandler implements InputDeviceListener {
 						}
 						}
 					}
 					}
 
 
-					joysticksDevices.add(joy);
+					mJoysticksDevices.add(joy);
 
 
 					final int device_id = id;
 					final int device_id = id;
 					final String name = joy.name;
 					final String name = joy.name;
@@ -270,7 +270,7 @@ public class GodotInputHandler implements InputDeviceListener {
 
 
 		// Check if the evice has not been already removed
 		// Check if the evice has not been already removed
 		if (device_id > -1) {
 		if (device_id > -1) {
-			joysticksDevices.remove(device_id);
+			mJoysticksDevices.remove(device_id);
 
 
 			queueEvent(new Runnable() {
 			queueEvent(new Runnable() {
 				@Override
 				@Override
@@ -360,8 +360,8 @@ public class GodotInputHandler implements InputDeviceListener {
 	}
 	}
 
 
 	private int findJoystickDevice(int device_id) {
 	private int findJoystickDevice(int device_id) {
-		for (int i = 0; i < joysticksDevices.size(); i++) {
-			if (joysticksDevices.get(i).device_id == device_id) {
+		for (int i = 0; i < mJoysticksDevices.size(); i++) {
+			if (mJoysticksDevices.get(i).device_id == device_id) {
 				return i;
 				return i;
 			}
 			}
 		}
 		}

+ 11 - 11
platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java

@@ -48,7 +48,7 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
 	// ===========================================================
 	// ===========================================================
 	// Fields
 	// Fields
 	// ===========================================================
 	// ===========================================================
-	private final GodotView mView;
+	private final GodotRenderView mRenderView;
 	private final GodotEditText mEdit;
 	private final GodotEditText mEdit;
 	private String mOriginText;
 	private String mOriginText;
 
 
@@ -56,9 +56,9 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
 	// Constructors
 	// Constructors
 	// ===========================================================
 	// ===========================================================
 
 
-	public GodotTextInputWrapper(final GodotView view, final GodotEditText edit) {
-		this.mView = view;
-		this.mEdit = edit;
+	public GodotTextInputWrapper(final GodotRenderView view, final GodotEditText edit) {
+		mRenderView = view;
+		mEdit = edit;
 	}
 	}
 
 
 	// ===========================================================
 	// ===========================================================
@@ -66,13 +66,13 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
 	// ===========================================================
 	// ===========================================================
 
 
 	private boolean isFullScreenEdit() {
 	private boolean isFullScreenEdit() {
-		final TextView textField = this.mEdit;
+		final TextView textField = mEdit;
 		final InputMethodManager imm = (InputMethodManager)textField.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
 		final InputMethodManager imm = (InputMethodManager)textField.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
 		return imm.isFullscreenMode();
 		return imm.isFullscreenMode();
 	}
 	}
 
 
 	public void setOriginText(final String originText) {
 	public void setOriginText(final String originText) {
-		this.mOriginText = originText;
+		mOriginText = originText;
 	}
 	}
 
 
 	// ===========================================================
 	// ===========================================================
@@ -87,7 +87,7 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
 	public void beforeTextChanged(final CharSequence pCharSequence, final int start, final int count, final int after) {
 	public void beforeTextChanged(final CharSequence pCharSequence, final int start, final int count, final int after) {
 		//Log.d(TAG, "beforeTextChanged(" + pCharSequence + ")start: " + start + ",count: " + count + ",after: " + after);
 		//Log.d(TAG, "beforeTextChanged(" + pCharSequence + ")start: " + start + ",count: " + count + ",after: " + after);
 
 
-		mView.queueEvent(new Runnable() {
+		mRenderView.queueOnRenderThread(new Runnable() {
 			@Override
 			@Override
 			public void run() {
 			public void run() {
 				for (int i = 0; i < count; ++i) {
 				for (int i = 0; i < count; ++i) {
@@ -106,7 +106,7 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
 		for (int i = start; i < start + count; ++i) {
 		for (int i = start; i < start + count; ++i) {
 			newChars[i - start] = pCharSequence.charAt(i);
 			newChars[i - start] = pCharSequence.charAt(i);
 		}
 		}
-		mView.queueEvent(new Runnable() {
+		mRenderView.queueOnRenderThread(new Runnable() {
 			@Override
 			@Override
 			public void run() {
 			public void run() {
 				for (int i = 0; i < count; ++i) {
 				for (int i = 0; i < count; ++i) {
@@ -124,10 +124,10 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
 
 
 	@Override
 	@Override
 	public boolean onEditorAction(final TextView pTextView, final int pActionID, final KeyEvent pKeyEvent) {
 	public boolean onEditorAction(final TextView pTextView, final int pActionID, final KeyEvent pKeyEvent) {
-		if (this.mEdit == pTextView && this.isFullScreenEdit()) {
+		if (mEdit == pTextView && isFullScreenEdit()) {
 			final String characters = pKeyEvent.getCharacters();
 			final String characters = pKeyEvent.getCharacters();
 
 
-			mView.queueEvent(new Runnable() {
+			mRenderView.queueOnRenderThread(new Runnable() {
 				@Override
 				@Override
 				public void run() {
 				public void run() {
 					for (int i = 0; i < characters.length(); i++) {
 					for (int i = 0; i < characters.length(); i++) {
@@ -144,7 +144,7 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
 			GodotLib.key(KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_ENTER, 0, true);
 			GodotLib.key(KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_ENTER, 0, true);
 			GodotLib.key(KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_ENTER, 0, false);
 			GodotLib.key(KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_ENTER, 0, false);
 
 
-			this.mView.requestFocus();
+			mRenderView.getView().requestFocus();
 			return true;
 			return true;
 		}
 		}
 		return false;
 		return false;

+ 30 - 13
platform/android/java/lib/src/org/godotengine/godot/vulkan/VkRenderer.kt

@@ -33,6 +33,11 @@ package org.godotengine.godot.vulkan
 
 
 import android.view.Surface
 import android.view.Surface
 
 
+import org.godotengine.godot.Godot
+import org.godotengine.godot.GodotLib
+import org.godotengine.godot.plugin.GodotPlugin
+import org.godotengine.godot.plugin.GodotPluginRegistry
+
 /**
 /**
  * Responsible to setting up and driving the Vulkan rendering logic.
  * Responsible to setting up and driving the Vulkan rendering logic.
  *
  *
@@ -48,52 +53,64 @@ import android.view.Surface
  */
  */
 internal class VkRenderer {
 internal class VkRenderer {
 
 
+	private val pluginRegistry: GodotPluginRegistry = GodotPluginRegistry.getPluginRegistry()
+
 	/**
 	/**
 	 * Called when the surface is created and signals the beginning of rendering.
 	 * Called when the surface is created and signals the beginning of rendering.
 	 */
 	 */
 	fun onVkSurfaceCreated(surface: Surface) {
 	fun onVkSurfaceCreated(surface: Surface) {
-		nativeOnVkSurfaceCreated(surface)
+		// TODO: properly implement surface re-creation:
+		// GodotLib.newcontext should be called here once it's done.
+		//GodotLib.newcontext(surface, false)
+
+		for (plugin in pluginRegistry.getAllPlugins()) {
+			plugin.onVkSurfaceCreated(surface)
+		}
 	}
 	}
 
 
 	/**
 	/**
 	 * Called after the surface is created and whenever its size changes.
 	 * Called after the surface is created and whenever its size changes.
 	 */
 	 */
 	fun onVkSurfaceChanged(surface: Surface, width: Int, height: Int) {
 	fun onVkSurfaceChanged(surface: Surface, width: Int, height: Int) {
-		nativeOnVkSurfaceChanged(surface, width, height)
+		GodotLib.resize(width, height)
+		
+		// TODO: properly implement surface re-creation:
+		// Update the native renderer instead of restarting the app.
+		// GodotLib.newcontext should not be called here once it's done.
+		GodotLib.newcontext(surface, false)
+		
+		for (plugin in pluginRegistry.getAllPlugins()) {
+			plugin.onVkSurfaceChanged(surface, width, height)
+		}
 	}
 	}
 
 
 	/**
 	/**
 	 * Called to draw the current frame.
 	 * Called to draw the current frame.
 	 */
 	 */
 	fun onVkDrawFrame() {
 	fun onVkDrawFrame() {
-		nativeOnVkDrawFrame()
+		GodotLib.step()
+		for (plugin in pluginRegistry.getAllPlugins()) {
+			plugin.onVkDrawFrame()
+		}
 	}
 	}
 
 
 	/**
 	/**
 	 * Called when the rendering thread is resumed.
 	 * Called when the rendering thread is resumed.
 	 */
 	 */
 	fun onVkResume() {
 	fun onVkResume() {
-		nativeOnVkResume()
+		GodotLib.onRendererResumed()
 	}
 	}
 
 
 	/**
 	/**
 	 * Called when the rendering thread is paused.
 	 * Called when the rendering thread is paused.
 	 */
 	 */
 	fun onVkPause() {
 	fun onVkPause() {
-		nativeOnVkPause()
+		GodotLib.onRendererPaused()
 	}
 	}
 
 
 	/**
 	/**
 	 * Called when the rendering thread is destroyed and used as signal to tear down the Vulkan logic.
 	 * Called when the rendering thread is destroyed and used as signal to tear down the Vulkan logic.
 	 */
 	 */
 	fun onVkDestroy() {
 	fun onVkDestroy() {
-		nativeOnVkDestroy()
 	}
 	}
-
-	private external fun nativeOnVkSurfaceCreated(surface: Surface)
-	private external fun nativeOnVkSurfaceChanged(surface: Surface, width: Int, height: Int)
-	private external fun nativeOnVkResume()
-	private external fun nativeOnVkDrawFrame()
-	private external fun nativeOnVkPause()
-	private external fun nativeOnVkDestroy()
 }
 }

+ 3 - 3
platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt

@@ -49,7 +49,7 @@ import android.view.SurfaceView
  * UI thread.
  * UI thread.
  * </ul>
  * </ul>
  */
  */
-internal class VkSurfaceView(context: Context) : SurfaceView(context), SurfaceHolder.Callback {
+open internal class VkSurfaceView(context: Context) : SurfaceView(context), SurfaceHolder.Callback {
 
 
 	companion object {
 	companion object {
 		fun checkState(expression: Boolean, errorMessage: Any) {
 		fun checkState(expression: Boolean, errorMessage: Any) {
@@ -100,7 +100,7 @@ internal class VkSurfaceView(context: Context) : SurfaceView(context), SurfaceHo
 	 *
 	 *
 	 * Must not be called before a [VkRenderer] has been set.
 	 * Must not be called before a [VkRenderer] has been set.
 	 */
 	 */
-	fun onResume() {
+	open fun onResume() {
 		vkThread.onResume()
 		vkThread.onResume()
 	}
 	}
 
 
@@ -109,7 +109,7 @@ internal class VkSurfaceView(context: Context) : SurfaceView(context), SurfaceHo
 	 *
 	 *
 	 * Must not be called before a [VkRenderer] has been set.
 	 * Must not be called before a [VkRenderer] has been set.
 	 */
 	 */
-	fun onPause() {
+	open fun onPause() {
 		vkThread.onPause()
 		vkThread.onPause()
 	}
 	}
 
 

+ 2 - 2
platform/android/java/lib/src/org/godotengine/godot/vulkan/VkThread.kt

@@ -219,9 +219,9 @@ internal class VkThread(private val vkSurfaceView: VkSurfaceView, private val vk
 				vkRenderer.onVkDrawFrame()
 				vkRenderer.onVkDrawFrame()
 			}
 			}
 		} catch (ex: InterruptedException) {
 		} catch (ex: InterruptedException) {
-			Log.i(TAG, ex.message)
+			Log.i(TAG, "InterruptedException", ex)
 		} catch (ex: IllegalStateException) {
 		} catch (ex: IllegalStateException) {
-			Log.i(TAG, ex.message)
+			Log.i(TAG, "IllegalStateException", ex)
 		} finally {
 		} finally {
 			threadExiting()
 			threadExiting()
 		}
 		}

+ 0 - 1
platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java

@@ -51,7 +51,6 @@ public class RegularContextFactory implements GLSurfaceView.EGLContextFactory {
 	private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
 	private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
 
 
 	public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
 	public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
-		String driver_name = GodotLib.getGlobal("rendering/quality/driver/driver_name");
 		// FIXME: Add support for Vulkan.
 		// FIXME: Add support for Vulkan.
 		Log.w(TAG, "creating OpenGL ES 2.0 context :");
 		Log.w(TAG, "creating OpenGL ES 2.0 context :");
 
 

+ 8 - 3
platform/android/java_godot_lib_jni.cpp

@@ -52,6 +52,8 @@
 
 
 #include <unistd.h>
 #include <unistd.h>
 
 
+#include <android/native_window_jni.h>
+
 static JavaClassWrapper *java_class_wrapper = nullptr;
 static JavaClassWrapper *java_class_wrapper = nullptr;
 static OS_Android *os_android = nullptr;
 static OS_Android *os_android = nullptr;
 static GodotJavaWrapper *godot_java = nullptr;
 static GodotJavaWrapper *godot_java = nullptr;
@@ -168,14 +170,17 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, j
 		os_android->set_display_size(Size2(width, height));
 		os_android->set_display_size(Size2(width, height));
 }
 }
 
 
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jclass clazz, jboolean p_32_bits) {
-
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jclass clazz, jobject p_surface, jboolean p_32_bits) {
 	if (os_android) {
 	if (os_android) {
 		if (step == 0) {
 		if (step == 0) {
 			// During startup
 			// During startup
 			os_android->set_context_is_16_bits(!p_32_bits);
 			os_android->set_context_is_16_bits(!p_32_bits);
+			if (p_surface) {
+				ANativeWindow *native_window = ANativeWindow_fromSurface(env, p_surface);
+				os_android->set_native_window(native_window);
+			}
 		} else {
 		} else {
-			// GL context recreated because it was lost; restart app to let it reload everything
+			// Rendering context recreated because it was lost; restart app to let it reload everything
 			os_android->main_loop_end();
 			os_android->main_loop_end();
 			godot_java->restart(env);
 			godot_java->restart(env);
 			step = -1; // Ensure no further steps are attempted
 			step = -1; // Ensure no further steps are attempted

+ 1 - 1
platform/android/java_godot_lib_jni.h

@@ -41,7 +41,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz, jobject activity);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz, jobject activity);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jclass clazz, jint width, jint height);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jclass clazz, jint width, jint height);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jclass clazz, jboolean p_32_bits);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jclass clazz, jobject p_surface, jboolean p_32_bits);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jclass clazz);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jclass clazz);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jclass clazz);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jclass clazz);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jclass clazz, jint ev, jint pointer, jint count, jintArray positions);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jclass clazz, jint ev, jint pointer, jint count, jintArray positions);

+ 58 - 19
platform/android/os_android.cpp

@@ -35,6 +35,11 @@
 #if defined(OPENGL_ENABLED)
 #if defined(OPENGL_ENABLED)
 #include "drivers/gles2/rasterizer_gles2.h"
 #include "drivers/gles2/rasterizer_gles2.h"
 #endif
 #endif
+#if defined(VULKAN_ENABLED)
+#include "drivers/vulkan/rendering_device_vulkan.h"
+#include "platform/android/vulkan/vulkan_context_android.h"
+#include "servers/visual/rasterizer_rd/rasterizer_rd.h"
+#endif
 #include "drivers/unix/dir_access_unix.h"
 #include "drivers/unix/dir_access_unix.h"
 #include "drivers/unix/file_access_unix.h"
 #include "drivers/unix/file_access_unix.h"
 #include "file_access_android.h"
 #include "file_access_android.h"
@@ -60,19 +65,6 @@ public:
 	virtual ~AndroidLogger() {}
 	virtual ~AndroidLogger() {}
 };
 };
 
 
-int OS_Android::get_video_driver_count() const {
-
-	return 2;
-}
-
-const char *OS_Android::get_video_driver_name(int p_driver) const {
-
-	switch (p_driver) {
-		case VIDEO_DRIVER_GLES2:
-			return "GLES2";
-	}
-	ERR_FAIL_V_MSG(nullptr, "Invalid video driver index: " + itos(p_driver) + ".");
-}
 int OS_Android::get_audio_driver_count() const {
 int OS_Android::get_audio_driver_count() const {
 
 
 	return 1;
 	return 1;
@@ -121,8 +113,7 @@ int OS_Android::get_current_video_driver() const {
 }
 }
 
 
 Error OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
 Error OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
-
-	// FIXME: Add Vulkan support. Readd fallback code from Vulkan to GLES2?
+	video_driver_index = p_video_driver;
 
 
 #if defined(OPENGL_ENABLED)
 #if defined(OPENGL_ENABLED)
 	if (video_driver_index == VIDEO_DRIVER_GLES2) {
 	if (video_driver_index == VIDEO_DRIVER_GLES2) {
@@ -144,7 +135,31 @@ Error OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int
 	}
 	}
 #endif
 #endif
 
 
-	video_driver_index = p_video_driver;
+#if defined(VULKAN_ENABLED)
+	if (video_driver_index == VIDEO_DRIVER_VULKAN) {
+		ERR_FAIL_COND_V(!native_window, ERR_UNAVAILABLE);
+
+		context_vulkan = memnew(VulkanContextAndroid);
+		if (context_vulkan->initialize() != OK) {
+			memdelete(context_vulkan);
+			context_vulkan = NULL;
+			ERR_FAIL_V(ERR_UNAVAILABLE);
+		}
+
+		Size2 window_size = get_window_size();
+		if (context_vulkan->window_create(native_window, window_size.width, window_size.height) == -1) {
+			memdelete(context_vulkan);
+			context_vulkan = NULL;
+			ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Failed to create Vulkan window.");
+		}
+
+		//temporary
+		rendering_device_vulkan = memnew(RenderingDeviceVulkan);
+		rendering_device_vulkan->initialize(context_vulkan);
+
+		RasterizerRD::make_current();
+	}
+#endif
 
 
 	rendering_server = memnew(RenderingServerRaster);
 	rendering_server = memnew(RenderingServerRaster);
 	if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
 	if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
@@ -175,6 +190,19 @@ void OS_Android::delete_main_loop() {
 void OS_Android::finalize() {
 void OS_Android::finalize() {
 
 
 	memdelete(input);
 	memdelete(input);
+
+#if defined(VULKAN_ENABLED)
+	if (video_driver_index == VIDEO_DRIVER_VULKAN) {
+		if (rendering_device_vulkan) {
+			rendering_device_vulkan->finalize();
+			memdelete(rendering_device_vulkan);
+		}
+
+		if (context_vulkan) {
+			memdelete(context_vulkan);
+		}
+	}
+#endif
 }
 }
 
 
 GodotJavaWrapper *OS_Android::get_godot_java() {
 GodotJavaWrapper *OS_Android::get_godot_java() {
@@ -572,9 +600,8 @@ void OS_Android::main_loop_request_go_back() {
 }
 }
 
 
 void OS_Android::set_display_size(Size2 p_size) {
 void OS_Android::set_display_size(Size2 p_size) {
-
-	default_videomode.width = p_size.x;
-	default_videomode.height = p_size.y;
+	default_videomode.width = p_size.width;
+	default_videomode.height = p_size.height;
 }
 }
 
 
 Error OS_Android::shell_open(String p_uri) {
 Error OS_Android::shell_open(String p_uri) {
@@ -710,6 +737,12 @@ void OS_Android::set_context_is_16_bits(bool p_is_16) {
 	//	rasterizer->set_force_16_bits_fbo(p_is_16);
 	//	rasterizer->set_force_16_bits_fbo(p_is_16);
 }
 }
 
 
+void OS_Android::set_native_window(ANativeWindow *p_native_window) {
+#if defined(VULKAN_ENABLED)
+	native_window = p_native_window;
+#endif
+}
+
 void OS_Android::joy_connection_changed(int p_device, bool p_connected, String p_name) {
 void OS_Android::joy_connection_changed(int p_device, bool p_connected, String p_name) {
 	return input->joy_connection_changed(p_device, p_connected, p_name, "");
 	return input->joy_connection_changed(p_device, p_connected, p_name, "");
 }
 }
@@ -759,6 +792,12 @@ OS_Android::OS_Android(GodotJavaWrapper *p_godot_java, GodotIOJavaWrapper *p_god
 	//rasterizer = nullptr;
 	//rasterizer = nullptr;
 	use_gl2 = false;
 	use_gl2 = false;
 
 
+#if defined(VULKAN_ENABLED)
+	context_vulkan = NULL;
+	rendering_device_vulkan = NULL;
+	native_window = NULL;
+#endif
+
 	rendering_server = nullptr;
 	rendering_server = nullptr;
 
 
 	godot_java = p_godot_java;
 	godot_java = p_godot_java;

+ 15 - 4
platform/android/os_android.h

@@ -42,6 +42,13 @@
 class GodotJavaWrapper;
 class GodotJavaWrapper;
 class GodotIOJavaWrapper;
 class GodotIOJavaWrapper;
 
 
+#if defined(VULKAN_ENABLED)
+class VulkanContextAndroid;
+class RenderingDeviceVulkan;
+#endif
+
+struct ANativeWindow;
+
 class OS_Android : public OS_Unix {
 class OS_Android : public OS_Unix {
 public:
 public:
 	struct TouchPos {
 	struct TouchPos {
@@ -75,6 +82,12 @@ private:
 
 
 	bool use_16bits_fbo;
 	bool use_16bits_fbo;
 
 
+#if defined(VULKAN_ENABLED)
+	VulkanContextAndroid *context_vulkan;
+	RenderingDeviceVulkan *rendering_device_vulkan;
+	ANativeWindow *native_window;
+#endif
+
 	RenderingServer *rendering_server;
 	RenderingServer *rendering_server;
 
 
 	mutable String data_dir_cache;
 	mutable String data_dir_cache;
@@ -94,10 +107,6 @@ private:
 	int video_driver_index;
 	int video_driver_index;
 
 
 public:
 public:
-	// functions used by main to initialize/deinitialize the OS
-	virtual int get_video_driver_count() const;
-	virtual const char *get_video_driver_name(int p_driver) const;
-
 	virtual int get_audio_driver_count() const;
 	virtual int get_audio_driver_count() const;
 	virtual const char *get_audio_driver_name(int p_driver) const;
 	virtual const char *get_audio_driver_name(int p_driver) const;
 
 
@@ -163,6 +172,8 @@ public:
 
 
 	void set_context_is_16_bits(bool p_is_16);
 	void set_context_is_16_bits(bool p_is_16);
 
 
+	void set_native_window(ANativeWindow *p_native_window);
+
 	virtual void set_screen_orientation(ScreenOrientation p_orientation);
 	virtual void set_screen_orientation(ScreenOrientation p_orientation);
 
 
 	virtual Error shell_open(String p_uri);
 	virtual Error shell_open(String p_uri);

+ 68 - 0
platform/android/vulkan/vulkan_context_android.cpp

@@ -0,0 +1,68 @@
+/*************************************************************************/
+/*  vulkan_context_android.cpp                                           */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "vulkan_context_android.h"
+#include <vulkan/vulkan_android.h>
+
+#define VMA_IMPLEMENTATION
+#ifdef DEBUG_ENABLED
+#ifndef _MSC_VER
+#define _DEBUG
+#endif
+#endif
+#include <vk_mem_alloc.h>
+
+const char *VulkanContextAndroid::_get_platform_surface_extension() const {
+	return VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
+}
+
+int VulkanContextAndroid::window_create(ANativeWindow *p_window, int p_width, int p_height) {
+	VkAndroidSurfaceCreateInfoKHR createInfo;
+	createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
+	createInfo.pNext = NULL;
+	createInfo.flags = 0;
+	createInfo.window = p_window;
+
+	VkSurfaceKHR surface;
+	VkResult err = vkCreateAndroidSurfaceKHR(_get_instance(), &createInfo, NULL, &surface);
+	if (err != VK_SUCCESS) {
+		ERR_FAIL_V_MSG(-1, "vkCreateAndroidSurfaceKHR failed with error " + itos(err));
+	}
+
+	return _window_create(surface, p_width, p_height);
+}
+
+VulkanContextAndroid::VulkanContextAndroid() {
+	// TODO: fix validation layers
+	use_validation_layers = false;
+}
+
+VulkanContextAndroid::~VulkanContextAndroid() {
+}

+ 13 - 22
platform/android/vulkan/vk_renderer_jni.cpp → platform/android/vulkan/vulkan_context_android.h

@@ -1,5 +1,5 @@
 /*************************************************************************/
 /*************************************************************************/
-/*  vk_renderer_jni.cpp                                                  */
+/*  vulkan_context_android.h                                             */
 /*************************************************************************/
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
 /*                           GODOT ENGINE                                */
@@ -28,31 +28,22 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 /*************************************************************************/
 
 
-#include "vk_renderer_jni.h"
+#ifndef VULKAN_CONTEXT_ANDROID_H
+#define VULKAN_CONTEXT_ANDROID_H
 
 
-extern "C" {
+#include "drivers/vulkan/vulkan_context.h"
 
 
-JNIEXPORT void JNICALL Java_org_godotengine_godot_vulkan_VkRenderer_nativeOnVkSurfaceCreated(JNIEnv *env, jobject obj, jobject j_surface) {
-	// TODO: complete
-}
+struct ANativeWindow;
 
 
-JNIEXPORT void JNICALL Java_org_godotengine_godot_vulkan_VkRenderer_nativeOnVkSurfaceChanged(JNIEnv *env, jobject object, jobject j_surface, jint width, jint height) {
-	// TODO: complete
-}
+class VulkanContextAndroid : public VulkanContext {
 
 
-JNIEXPORT void JNICALL Java_org_godotengine_godot_vulkan_VkRenderer_nativeOnVkResume(JNIEnv *env, jobject obj) {
-	// TODO: complete
-}
+	virtual const char *_get_platform_surface_extension() const;
 
 
-JNIEXPORT void JNICALL Java_org_godotengine_godot_vulkan_VkRenderer_nativeOnVkDrawFrame(JNIEnv *env, jobject obj) {
-	// TODO: complete
-}
+public:
+	int window_create(ANativeWindow *p_window, int p_width, int p_height);
 
 
-JNIEXPORT void JNICALL Java_org_godotengine_godot_vulkan_VkRenderer_nativeOnVkPause(JNIEnv *env, jobject obj) {
-	// TODO: complete
-}
+	VulkanContextAndroid();
+	~VulkanContextAndroid();
+};
 
 
-JNIEXPORT void JNICALL Java_org_godotengine_godot_vulkan_VkRenderer_nativeOnVkDestroy(JNIEnv *env, jobject obj) {
-	// TODO: complete
-}
-}
+#endif // VULKAN_CONTEXT_ANDROID_H