Skip to content

Commit 9ed5f31

Browse files
committed
Unify and clean-up Godot Android surface allocation and render thread logic
1 parent 7c472e6 commit 9ed5f31

21 files changed

+1013
-935
lines changed

platform/android/java/editor/src/main/java/org/godotengine/editor/BaseGodotEditor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
316316

317317
runOnUiThread {
318318
// Enable long press, panning and scaling gestures
319-
godotFragment?.godot?.renderView?.inputHandler?.apply {
319+
godotFragment?.godot?.godotInputHandler?.apply {
320320
enableLongPress(longPressEnabled)
321321
enablePanningAndScalingGestures(panScaleEnabled)
322322
setOverrideVolumeButtons(overrideVolumeButtonsEnabled)

platform/android/java/lib/src/org/godotengine/godot/Godot.kt

Lines changed: 60 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ import org.godotengine.godot.io.file.FileAccessHandler
6262
import org.godotengine.godot.plugin.AndroidRuntimePlugin
6363
import org.godotengine.godot.plugin.GodotPlugin
6464
import org.godotengine.godot.plugin.GodotPluginRegistry
65+
import org.godotengine.godot.render.GodotGLRenderView
66+
import org.godotengine.godot.render.GodotRenderer
67+
import org.godotengine.godot.render.GodotVulkanRenderView
68+
import org.godotengine.godot.render.Renderer
6569
import org.godotengine.godot.tts.GodotTTS
6670
import org.godotengine.godot.utils.DialogUtils
6771
import org.godotengine.godot.utils.GodotNetUtils
@@ -112,6 +116,8 @@ class Godot private constructor(val context: Context) {
112116
internal fun isEditorBuild() = BuildConfig.FLAVOR == EDITOR_FLAVOR
113117
}
114118

119+
private lateinit var renderer: GodotRenderer
120+
115121
private val mSensorManager: SensorManager? by lazy { context.getSystemService(Context.SENSOR_SERVICE) as? SensorManager }
116122
private val mClipboard: ClipboardManager? by lazy { context.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager }
117123
private val vibratorService: Vibrator? by lazy { context.getSystemService(Context.VIBRATOR_SERVICE) as? Vibrator }
@@ -133,7 +139,7 @@ class Godot private constructor(val context: Context) {
133139
val directoryAccessHandler = DirectoryAccessHandler(context)
134140
val fileAccessHandler = FileAccessHandler(context)
135141
val netUtils = GodotNetUtils(context)
136-
private val godotInputHandler = GodotInputHandler(context, this)
142+
val godotInputHandler = GodotInputHandler(context, this)
137143

138144
/**
139145
* Task to run when the engine terminates.
@@ -182,18 +188,23 @@ class Godot private constructor(val context: Context) {
182188
/**
183189
* Returns true if the native engine has been initialized through [onInitNativeLayer], false otherwise.
184190
*/
185-
private fun isNativeInitialized() = nativeLayerInitializeCompleted && nativeLayerSetupCompleted
191+
private fun isNativeInitialized() = nativeLayerInitializeCompleted && nativeLayerSetupCompleted && ::renderer.isInitialized
186192

187193
/**
188194
* Returns true if the engine has been initialized, false otherwise.
189195
*/
190196
fun isInitialized() = primaryHost != null && isNativeInitialized() && renderViewInitialized
191197

192198
/**
193-
* Provides access to the primary host [Activity]
199+
* Provides access to the primary host [Activity].
194200
*/
195201
fun getActivity() = primaryHost?.activity
196202

203+
/**
204+
* Provides access to the Godot [Renderer].
205+
*/
206+
fun getRenderer(): Renderer = renderer
207+
197208
/**
198209
* Start initialization of the Godot engine.
199210
*
@@ -331,6 +342,21 @@ class Godot private constructor(val context: Context) {
331342
Log.v(TAG, "Godot native layer setup completed")
332343
}
333344
}
345+
346+
val useVulkan = if (usesVulkan()) {
347+
if (meetsVulkanRequirements(context.packageManager)) {
348+
true
349+
} else if (canFallbackToOpenGL()) {
350+
// Fallback to OpenGl.
351+
false
352+
} else {
353+
throw IllegalStateException(context.getString(R.string.error_missing_vulkan_requirements_message))
354+
}
355+
} else {
356+
false
357+
}
358+
renderer = GodotRenderer(useVulkan)
359+
renderer.startRenderer()
334360
} finally {
335361
endBenchmarkMeasure("Startup", "Godot::initEngine")
336362
}
@@ -489,23 +515,13 @@ class Godot private constructor(val context: Context) {
489515
val shouldBeTransparent =
490516
!isProjectManagerHint() && !isEditorHint() && java.lang.Boolean.parseBoolean(GodotLib.getGlobal("display/window/per_pixel_transparency/allowed"))
491517
Log.d(TAG, "Render view should be transparent: $shouldBeTransparent")
492-
renderView = if (usesVulkan()) {
493-
if (meetsVulkanRequirements(context.packageManager)) {
494-
GodotVulkanRenderView(this, godotInputHandler, shouldBeTransparent)
495-
} else if (canFallbackToOpenGL()) {
496-
// Fallback to OpenGl.
497-
GodotGLRenderView(this, godotInputHandler, xrMode, useDebugOpengl, shouldBeTransparent)
498-
} else {
499-
throw IllegalStateException(context.getString(R.string.error_missing_vulkan_requirements_message))
500-
}
501-
518+
renderView = if (renderer.useVulkan) {
519+
GodotVulkanRenderView(this, renderer, godotInputHandler, shouldBeTransparent)
502520
} else {
503-
// Fallback to OpenGl.
504-
GodotGLRenderView(this, godotInputHandler, xrMode, useDebugOpengl, shouldBeTransparent)
521+
GodotGLRenderView(this, renderer, godotInputHandler, xrMode, useDebugOpengl, shouldBeTransparent)
505522
}
506523

507524
renderView?.let {
508-
it.startRenderer()
509525
containerLayout?.addView(
510526
it.view,
511527
ViewGroup.LayoutParams(
@@ -557,7 +573,7 @@ class Godot private constructor(val context: Context) {
557573
override fun onEnd(animation: WindowInsetsAnimationCompat) {}
558574
})
559575

560-
renderView?.queueOnRenderThread {
576+
runOnRenderThread {
561577
for (plugin in pluginRegistry.allPlugins) {
562578
plugin.onRegisterPluginWithGodotNative()
563579
}
@@ -593,7 +609,10 @@ class Godot private constructor(val context: Context) {
593609
return
594610
}
595611

596-
renderView?.onActivityStarted()
612+
renderer.onActivityStarted()
613+
for (plugin in pluginRegistry.allPlugins) {
614+
plugin.onMainStart()
615+
}
597616
}
598617

599618
fun onResume(host: GodotHost) {
@@ -603,7 +622,7 @@ class Godot private constructor(val context: Context) {
603622
return
604623
}
605624

606-
renderView?.onActivityResumed()
625+
renderer.onActivityResumed()
607626
registerSensorsIfNeeded()
608627
for (plugin in pluginRegistry.allPlugins) {
609628
plugin.onMainResume()
@@ -636,11 +655,11 @@ class Godot private constructor(val context: Context) {
636655
return
637656
}
638657

639-
renderView?.onActivityPaused()
640-
mSensorManager?.unregisterListener(godotInputHandler)
641658
for (plugin in pluginRegistry.allPlugins) {
642659
plugin.onMainPause()
643660
}
661+
renderer.onActivityPaused()
662+
mSensorManager?.unregisterListener(godotInputHandler)
644663
}
645664

646665
fun onStop(host: GodotHost) {
@@ -649,7 +668,10 @@ class Godot private constructor(val context: Context) {
649668
return
650669
}
651670

652-
renderView?.onActivityStopped()
671+
for (plugin in pluginRegistry.allPlugins) {
672+
plugin.onMainStop()
673+
}
674+
renderer.onActivityStopped()
653675
}
654676

655677
fun onDestroy(primaryHost: GodotHost) {
@@ -658,12 +680,22 @@ class Godot private constructor(val context: Context) {
658680
}
659681
Log.v(TAG, "OnDestroy: $primaryHost")
660682

683+
// If the host activity is being destroyed because it's changing configurations, it'll be recreated, so we keep
684+
// the engine around to continue where we left off.
685+
val isHostChangingConfigurations = primaryHost.activity?.isChangingConfigurations == true
686+
if (!isHostChangingConfigurations) {
687+
destroyEngine()
688+
}
689+
this.primaryHost = null
690+
}
691+
692+
private fun destroyEngine() {
693+
Log.d(TAG, "Destroying Godot Engine")
661694
for (plugin in pluginRegistry.allPlugins) {
662695
plugin.onMainDestroy()
663696
}
664697

665-
renderView?.onActivityDestroyed()
666-
this.primaryHost = null
698+
renderer.onActivityDestroyed()
667699
}
668700

669701
/**
@@ -724,7 +756,7 @@ class Godot private constructor(val context: Context) {
724756
val scrollDeadzoneDisabled = java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/disable_scroll_deadzone"))
725757

726758
runOnHostThread {
727-
renderView?.inputHandler?.apply {
759+
godotInputHandler.apply {
728760
enableLongPress(longPressEnabled)
729761
enablePanningAndScalingGestures(panScaleEnabled)
730762
setOverrideVolumeButtons(overrideVolumeButtons)
@@ -811,7 +843,7 @@ class Godot private constructor(val context: Context) {
811843
* This must be called after the render thread has started.
812844
*/
813845
fun runOnRenderThread(action: Runnable) {
814-
renderView?.queueOnRenderThread(action)
846+
renderer.queueOnRenderThread(action)
815847
}
816848

817849
/**
@@ -983,7 +1015,7 @@ class Godot private constructor(val context: Context) {
9831015
runOnTerminate.set(destroyRunnable)
9841016

9851017
runOnHostThread {
986-
onDestroy(host)
1018+
destroyEngine()
9871019
}
9881020
}
9891021

@@ -1003,7 +1035,7 @@ class Godot private constructor(val context: Context) {
10031035
for (plugin in pluginRegistry.allPlugins) {
10041036
plugin.onMainBackPressed()
10051037
}
1006-
renderView?.queueOnRenderThread { GodotLib.back() }
1038+
runOnRenderThread { GodotLib.back() }
10071039
}
10081040

10091041
/**

platform/android/java/lib/src/org/godotengine/godot/GodotLib.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@
3030

3131
package org.godotengine.godot;
3232

33-
import org.godotengine.godot.gl.GodotRenderer;
3433
import org.godotengine.godot.io.directory.DirectoryAccessHandler;
3534
import org.godotengine.godot.io.file.FileAccessHandler;
35+
import org.godotengine.godot.render.GodotRenderer;
3636
import org.godotengine.godot.tts.GodotTTS;
3737
import org.godotengine.godot.utils.GodotNetUtils;
3838
import org.godotengine.godot.variant.Callable;
@@ -42,8 +42,6 @@
4242
import android.hardware.SensorEvent;
4343
import android.view.Surface;
4444

45-
import javax.microedition.khronos.opengles.GL10;
46-
4745
/**
4846
* Wrapper for native library
4947
*/
@@ -81,7 +79,7 @@ public static native boolean initialize(
8179
* @param p_surface
8280
* @param p_width
8381
* @param p_height
84-
* @see org.godotengine.godot.gl.GLSurfaceView.Renderer#onSurfaceChanged(GL10, int, int)
82+
* @see GodotRenderer#onRenderSurfaceChanged(Surface, int, int)
8583
*/
8684
public static native void resize(Surface p_surface, int p_width, int p_height);
8785

@@ -98,7 +96,7 @@ public static native boolean initialize(
9896

9997
/**
10098
* Invoked on the GL thread to draw the current frame.
101-
* @see org.godotengine.godot.gl.GLSurfaceView.Renderer#onDrawFrame(GL10)
99+
* @see GodotRenderer#onRenderDrawFrame()
102100
*/
103101
public static native boolean step();
104102

platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,26 +38,6 @@
3838
public interface GodotRenderView {
3939
SurfaceView getView();
4040

41-
/**
42-
* Starts the thread that will drive Godot's rendering.
43-
*/
44-
void startRenderer();
45-
46-
/**
47-
* Queues a runnable to be run on the rendering thread.
48-
*/
49-
void queueOnRenderThread(Runnable event);
50-
51-
void onActivityPaused();
52-
53-
void onActivityStopped();
54-
55-
void onActivityResumed();
56-
57-
void onActivityStarted();
58-
59-
void onActivityDestroyed();
60-
6141
GodotInputHandler getInputHandler();
6242

6343
void configurePointerIcon(int pointerType, String imagePath, float hotSpotX, float hotSpotY);

platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,16 @@ public void onMainRequestPermissionsResult(int requestCode, String[] permissions
206206
*/
207207
public void onMainPause() {}
208208

209+
/**
210+
* @see Activity#onStop()
211+
*/
212+
public void onMainStop() {}
213+
214+
/**
215+
* @see Activity#onStart()
216+
*/
217+
public void onMainStart() {}
218+
209219
/**
210220
* @see Activity#onResume()
211221
*/
@@ -238,37 +248,71 @@ public void onGodotMainLoopStarted() {}
238248
/**
239249
* When using the OpenGL renderer, this is invoked once per frame on the GL thread after the
240250
* frame is drawn.
251+
*
252+
* @deprecated Use {@link #onRenderDrawFrame()} instead.
241253
*/
254+
@Deprecated
242255
public void onGLDrawFrame(GL10 gl) {}
243256

244257
/**
245258
* When using the OpenGL renderer, this is called on the GL thread after the surface is created
246259
* and whenever the OpenGL ES surface size changes.
260+
*
261+
* @deprecated Use {@link #onRenderSurfaceChanged(Surface, int, int)} instead.
247262
*/
263+
@Deprecated
248264
public void onGLSurfaceChanged(GL10 gl, int width, int height) {}
249265

250266
/**
251267
* When using the OpenGL renderer, this is called on the GL thread when the surface is created
252268
* or recreated.
269+
*
270+
* @deprecated Use {@link #onRenderSurfaceCreated(Surface)} instead.
253271
*/
272+
@Deprecated
254273
public void onGLSurfaceCreated(GL10 gl, EGLConfig config) {}
255274

275+
/**
276+
* This is called on the render thread when the surface is created or recreated.
277+
*/
278+
public void onRenderSurfaceCreated(Surface surface) {}
279+
280+
/**
281+
* This is called on the render thread after the surface is created and whenever the surface
282+
* size changes.
283+
*/
284+
public void onRenderSurfaceChanged(Surface surface, int width, int height) {}
285+
286+
/**
287+
* Invoked once per frame on the render thread after the frame is drawn.
288+
*/
289+
public void onRenderDrawFrame() {}
290+
256291
/**
257292
* When using the Vulkan renderer, this is invoked once per frame on the Vulkan thread after
258293
* the frame is drawn.
294+
*
295+
* @deprecated Use {@link #onRenderDrawFrame()} instead.
259296
*/
297+
@Deprecated
260298
public void onVkDrawFrame() {}
261299

262300
/**
263301
* When using the Vulkan renderer, this is called on the Vulkan thread after the surface is
264302
* created and whenever the surface size changes.
303+
*
304+
* @deprecated Use {@link #onRenderSurfaceChanged(Surface, int, int)} instead.
265305
*/
306+
@Deprecated
266307
public void onVkSurfaceChanged(Surface surface, int width, int height) {}
267308

268309
/**
269310
* When using the Vulkan renderer, this is called on the Vulkan thread when the surface is
270311
* created or recreated.
312+
*
313+
* @deprecated Use {@link #onRenderSurfaceCreated(Surface)} instead.
271314
*/
315+
@Deprecated
272316
public void onVkSurfaceCreated(Surface surface) {}
273317

274318
/**

0 commit comments

Comments
 (0)