britzl/monarch

Remove flickering while transiting between screens with fade in/out

paweljarosz opened this issue · 25 comments

Flickering is visible when transiting between screen (at first there is no fade and the screen is visible in a blink of an eye and then screen gets black and then normally fades out)

Flickering when switching windows in Monarch is our big problem.
We use some ways of preload() to solve it, but it doesn't always work.
If there is any quick way to fix the flicker, that would be super great!

I'll try to take a look at the problem this evening. Could either of your perhaps share a small project where this happens or provide som instructions on how to configure the screens? You have transitions on both? None of them are preloaded?

Transitions are not used in our case.
In this case, the "preload" box is not checked.
The problem is clearly visible precisely because the project is large and the windows contain quite a lot of graphics.

@Morgerion and @paweljarosz Could you please try this branch: https://github.com/britzl/monarch/archive/refs/heads/dev-flicker.zip

It doesn't work - the project crashes before I can check the flickering.
I think this is due to standard monarch behaviour - if no preload checkbox is set for a window, it unloads it. And then it can't send a M.FOCUS.LOST to it.

DEBUG:SCRIPT: unloaded:	hash: [loading]	->  loaded:	hash: [story]
ERROR:SCRIPT: /monarch/monarch.lua:1066: /monarch/monarch.lua:481: Could not send message 'monarch_focus_lost' from 'launcher:/loading#screen' to 'loading:/GUI#loading'.
stack traceback:
	[C]: in function 'assert'
	/monarch/monarch.lua:1066: in function 'on_message'
	/monarch/screen_proxy.script:50: in function </monarch/screen_proxy.script:42>

Oh, that is strange. Could you please describe the setup of your screens and the Monarch functions you call when this happens?

I think I can share the whole project. This is the only right way.

I think I can share the whole project. This is the only right way.

Ok, either send a GitHub invite or email to bjorn@defold.se

Sent the link to the project.

I'm getting a crash on macOS when running the project:

DEBUG:SCRIPT: factory.create():	main:/bg#plain_road
DEBUG:SCRIPT: unloaded:	hash: [loading]	->  loaded:	hash: [story]
Assertion failed: (size <= Capacity()), function SetSize, file /Users/runner/work/defold/defold/tmp/dynamo_home/sdk/include/dmsdk/dlib/array.h, line 472.
INFO:CRASH: Successfully wrote Crashdump to file: /Users/bjornritzl/Library/Application Support/Defold/_crash
ERROR:CRASH: CALL STACK:

# 0 pc     0xd055fd libxslt.1.dylib _sigtramp+29

It's not a very helpful crash though... I'm guessing that I'm running out of resources. Instances perhaps...

We found out that it crashed because rgb etc1 (for android) and rgb pvrtc 4bppv1 (for ios) were used for backgrounds.
Now the project is running and working stably.

But option https://github.com/britzl/monarch/archive/refs/heads/dev-flicker.zip did not fix the problem.
The windows do not flicker only if they are checked "preload" in the collection settings.

@Morgerion I'm still getting a crash with the project you provided. I'd love to help out but the project your shared is pretty big and it is time consuming to tweak and build it. Can you please provide a smaller example of the flickering. issue?

@paweljarosz are you also still experiencing issues with flickering using this branch?

I have sent you another letter.
I think on a small project this problem will be less noticeable (or not noticeable at all), so I am in favour of considering the full case (with lots of textures in the window, which flickers before being showed).

I have an idea why this is happening.
When you call show(), the current window is hidden instantly, but to display the next window needs a few frames (at least one frame).
Thus, when switching between windows, there are frames where neither the first nor the second window is present.

When you call show(), the current window is hidden instantly, but to display the next window needs a few frames (at least one frame)

Hmm, but this is what I'm mitigating in the dev-flicker branch. The first screen is not unloaded until the second screen is loaded and visible. This is the general idea at least. If you compare the basic example between the master branch and dev-flicker branch you will notice a one frame flicker when navigating using monarch.show() on the master branch but this flicker is gone on the dev-flicker branch. I did however notice that there is a one frame flicker when using monarch.back().

In my case, it's about the windows that are loaded before show(), because they are not preloaded.
Today I checked the size of the gap (in frames) between closing one window and opening the next - on average 9 frames!
And as I already checked, dev-flicker doesn't solve this problem.

In my case, it's about the windows that are loaded before show(), because they are not preloaded

Are you using a collection proxy or factory? Loading should be handled properly, but apparently I have a problem somewhere. I'll try to reproduce this.

Today I checked the size of the gap (in frames) between closing one window and opening the next - on average 9 frames!

The 9 frames is probably the time it takes to load the resources.

dev-flicker doesn't solve this problem

I'm unable to reproduce the problem. This is what I have done:

  • I have two screens (S1 and S2)
  • Both are loaded through collection proxies.
  • Neither is preloaded.
  • S1 has no resources and consist of a simple gui with a button to load S2
  • S2 has two big atlases which take around 15 frames to load
  • When the button in S1 is pressed a normal monarch.show("screen2") is called
  • With the dev-flicker branch S1 is kept visible while S2 is loading
  • When S2 has loaded it is shown and S1 is unloaded
  • There is no frame where no screen is visible.

Could you please create a minimal example which shows your problem?

I've made a super-small test with a clearly visible flicker. Yes, it weighs 30 mb, because our project also uses a lot of resources, and this cannot be ruled out.

https://www.dropbox.com/s/3eice6uy4fgldgu/TEST.zip?dl=0

I've made a super-small test with a clearly visible flicker. Yes, it weighs 30 mb, because our project also uses a lot of resources, and this cannot be ruled out.

Thanks! Yes, with this example it is super clear that the background is visible for some time when navigating between "Window N1" and "Window N2".

BUT if you change to the branch I've been working on, https://github.com/britzl/monarch/archive/refs/heads/dev-flicker.zip, instead of https://github.com/britzl/monarch/archive/refs/tags/3.3.0.zip then there is no flicker at all.

OK, I tried using dev-flicker again on our project. And I get this stable bug:

image

Still, I think you have to look at the whole project.
Right now it is working stable.

Sent the link to the project.

OK, I tried using dev-flicker again on our project. And I get this stable bug:

I found the reason and will think of a fix.

  • The "loading" screen is shown
  • The "main" screen is shown with no_stack = true
  • The "loading" screen is unloaded and a focus lost message is sent
  • The "story" screen is shown
  • Since the "main" screen was not added to the stack Monarch attempts to hide the "loading" screen again, which fails since it was already unloaded.

I've applied a fix and merged to master with a new release: https://github.com/britzl/monarch/releases/tag/3.4.0