All the DynamicTextures dissapear after browser wakes up on Android

I use Google Chrome on my Android 13. I open some GUI examples (BABYLON.GUI.AdvancedDynamicTexture) and realized that when I go to some another app and return back to Google Chrome all GUI buttons dissapear. Meshes still stay there. I can even click that GUI button and it works but the texture has gone but if you click the emptiness you can click it :smiley:

The same behaviour I met when I saw all examples that draw a text using BABYLON.DynamicTexture.

It that known issue? How to deal with it? Maybe there some methods to reload those textures?

Android 13, Xiaomi Pad 6.

Ok, looks we can try to restore context this way: https://playground.babylonjs.com/#H2IPH3#22

I don’t reproduce on my Samsung Galaxy, Android 14, with this PG:

I don’t have Android 13, though.

I don’t think it’s about Android version…

Do you simply switch from a tab to another, then switch back? I don’t reproduce on my desktop PC either. What operating system are you using?

Yeah, I just go to my home screen and after 5-7 seconds of waiting, I go back to Chrome. It’s not refreshing, no unloading or something like this, but there is no the dynamic texture as well.

Android 13, Xiaomi Pad 6.

Tried this way but it doesn’t work in my case. When I go home screen from the app page and go back to it, in the console I see such messages:

WebGL: INVALID_OPERATION: restoreContext: context not lost
WebGL: CONTEXT_LOST_WEBGL: loseContext: context lost
BJS - [06:16:07]: WebGL context lost.
BJS - [06:16:08]: WebGL context successfully restored.
WebGL: INVALID_OPERATION: restoreContext: context not lost

but actually the DynamicTexture was lost and was not restored but it restored successfully all the meshes and its Texture (not DynamicTexture).

Ok, the good news here is that I can manually redraw a dynamic texture after a browser wakes up:

this._bjs.scene.render();
setTimeout( () =>
{
	const font = "bold 44px monospace";
	this._textureGround.drawText( "Grass", 75, 135, font, "green", "white", true, true );
	this._bjs.scene.render();
}, 0 );

Tried with only this line:

this._textureGround.update();

but it didn’t work. So the easy way is not for us :smiley:

Manually redrawing really saves the life. Almost. But sometimes dynamic textures stay black after browser wake up. And in this case we can set timeout value to, let’s say: 3000. Yeah, too much. But it works everytime. So, therefore we can call manually redrawing two times or more: setTimeout: 0ms and 3000ms to be sure it redraws successfully.

Strange, but I haven’t seen such behaviour in Firefox. It never goes black after browser wakes up. But instead of it, it refreshes the whole page manually :smiley:

I’m glad you could find a workaround!

It looks like it’s a specific problem with your device. Let’s see if other people can repro it.

Also, note that the WEBGL_lose_context extension should not be used in production code. It’s for debugging purpose only, to simulate context losts.

1 Like

Woah, thanks, I didn’t know this!

Could you please tell me, is there some way to redraw GUI. AdvancedDynamicTexture() in similar way? Anyway I can dispose all the GUI and create it again after browser wakes up but maybe there is some redrawing options already exist there

One more adding: when the GUI dynamictexture has gone after bromser wakes up, then I open Inspector in Playground, and it restores GUI textures. I think it’s because of resized canvas. Looks it has some redraw functions inside it but how to call it manually I don’t know.
It works for GUI AdvancedDynamicTextures (CreateFullscreenUI) only and not for DynamicTextures, and even not for AdvancedDynamicTexture (CreateForMesh). It’s all about canvas resize processing I suppose.

So I need to call something like on_resize() event on GUI.AdvancedDynamicTexture.

You can try to call invalidateRect like this:

const textureSize = adt.getSize();
adt.invalidateRect(0, 0, textureSize.width - 1, textureSize.height - 1);

You can also try to call adt.markAsDirty().

2 Likes

Wow, thanks for a great assumption! I use:

// After browser woke up, onfocus:
[ 0, 3000 ].forEach( timeout =>
{
	setTimeout( () =>
	{
		// this.draw_text_on_dynamic_texture_ground(); // worked
		this._dynamic_texture_on_text_ground_mesh.markAsDirty(); // didn't work
		this._advanced_ui_texture_fullscreen_ui.markAsDirty(); // worked!
		this._advanced_ui_texture_for_mesh.markAsDirty(); // worked!
	}, timeout );
}  );

That worked for AdvancedDynamicTexture (CreateFullscreenUI). Which is awesome!
And it didn’t work for a dynamic texture that drawn on _text_ground_mesh (CreateGround). In this case I can redraw a text again :smile:
It’s a pity that DynamicTexture doesn’t have makeAsDirty() method. Or does it named with some another name maybe? :smile:

No, there’s no method like markAsDirty() in DynamicTexture. In fact, a markAsDirty method will have to redraw the text, so it’s the same thing than calling drawText again.

2 Likes