Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Window white flash on init #914

Closed
Adarma opened this issue May 10, 2020 · 24 comments
Closed

Window white flash on init #914

Adarma opened this issue May 10, 2020 · 24 comments
Labels
shell/win concerns the Windows backend

Comments

@Adarma
Copy link

Adarma commented May 10, 2020

Is it possible to prevent the white flash that happens before the GUI is initially drawn?
Maybe just being able to choose black rather then a white flash is enough.
Seeing it in the examples on Windows.

@raphlinus
Copy link
Contributor

raphlinus commented May 11, 2020

I'm not personally seeing it, and at one time I spent considerable effort to avoid it. Are you on Windows 10? Is this a regression, ie do you still see it on older revs such as 9d7f3ab?

@Adarma
Copy link
Author

Adarma commented May 11, 2020

Sorry, should have said I'm seeing it on Win7x64.
It's 3am here in Germany, so I will check that commit tomorrow for regression

@xStrom
Copy link
Member

xStrom commented May 11, 2020

I can confirm that I also have the white flash, both during startup and during resize at the edges, with my Windows 7. It's not there on my Windows 10 machine.

@xStrom
Copy link
Member

xStrom commented May 11, 2020

I've been seeing this behavior for quite some time, so it's not a recent regression at least.

It seems to be performance related, because I see the initial white flash when cold starting an app, but not on restarts. I can force it by sleeping in paint of the root widget, including on Windows 10.

@xStrom
Copy link
Member

xStrom commented May 11, 2020

I managed to fix the white flash during resize in #915. It doesn't have an impact on the sleep based reproduction, however maybe the initial flash is caused by an issue that can't be represented by sleep. It will take time until I'll be able to know from my own experience, because I can't really reproduce cold starts easily.

@Adarma how often do you see the white flash? Always? Does it still happen with the change in #915?

@xStrom xStrom added bug does not behave the way it is supposed to shell/win concerns the Windows backend labels May 11, 2020
@xStrom
Copy link
Member

xStrom commented May 11, 2020

Okay I managed to get a cold start again and #915 does not fix the white flash. I'm still leaning towards thinking that this is performance related. Giving this some further thought, perhaps going to a full event cycle at the beginning is a mistake. All the caches are going to be cold and we need to go through full layout etc. Perhaps a solution is to have some sort of initial_paint event coming from druid-shell. It has the window size and druid can just do a simple fill with the background color. The idea being to get that first frame out with the correct background color, and then the second frame can be delayed due to it having to do peak work with cold caches.

@Adarma
Copy link
Author

Adarma commented May 11, 2020

I tested 9d7f3ab and it also happens with that.
I see it with every window create: every example, and every time I click "New window" in the multiwin example.
Yes, it still happens in #915 for me too.

@xStrom
Copy link
Member

xStrom commented May 11, 2020

I looked more closely into this and did some measuring with debug builds. The druid full event cycle is slow but remains under 8ms with the calculator example, which is what I'm using to test this. Most of the time during the first frame is actually spent creating the HWND render target, which clocks in at 39ms.

I moved the HWND render target creation to WM_CREATE instead, which is available in #916. @Adarma can you check if that helps with your situation?

@Adarma
Copy link
Author

Adarma commented May 11, 2020

I still get the same white flash with #916

Since you are testing with the calc example, I tried that. Strangely it seems completely broken for me now. Even on the current master commit 3878d31.
Is that just me? I get a white window which is unresponsive.
image

I went back to e7ec2d1 Druid 0.5 and calc does this:
image

The other examples seem to run fine (but with the white flash).
I recently installed Visual Studio 2019 Community. I'm wondering if that messed something up.

As you can see, I have a custom theme on Windows7, but that has never been an issue before.

Not sure if it is all related.

@xStrom
Copy link
Member

xStrom commented May 12, 2020

Okay so the completely unresponsive window is unexpected. I have not seen that myself nor have I heard of anyone else experiencing that.

I doubt VS 2019 has any effect, I have a ton of Visual Studios installed in parallel and they cause no issues.

The custom theme should not be an issue if other non-druid apps work fine.

Is there any information printed in the console when calc launches? On my Windows 7 I get:

ERROR [druid_shell::platform::windows::util] No shcore.dll
ERROR [druid_shell::platform::windows::util] Could not load `GetDpiForSystem`. Windows 10 or later is needed
ERROR [druid_shell::platform::windows::util] Could not load `CreateDXGIFactory2`. Windows 8.1 or later is needed
DEBUG [druid::localization] available locales [], current en-US
DEBUG [druid::localization] resolved: [en-US]

Do you have the same or something different?

Beyond that, you could add some logging into druid/druid/src/core.rs. Look up the WidgetPod implementation area, and then into the pub fn event / layout / paint add something like:

log::debug!("Reached this point);

Would be interesting to know if there's a hang of some sort, or if the event cycle is happening properly and the pixels just don't show up.

@Adarma
Copy link
Author

Adarma commented May 12, 2020

I get the exact same printout to the console as you when launching calc, then an error when I force terminate it.

cargo run --example calc
    Finished dev [unoptimized + debuginfo] target(s) in 0.63s
     Running `target\debug\examples\calc.exe`
ERROR [druid_shell::platform::windows::util] No shcore.dll
ERROR [druid_shell::platform::windows::util] Could not load `GetDpiForSystem`. Windows 10 or later is needed
ERROR [druid_shell::platform::windows::util] Could not load `CreateDXGIFactory2`. Windows 8.1 or later is needed
DEBUG [druid::localization] available locales [], current en-US
DEBUG [druid::localization] resolved: [en-US]
error: process didn't exit successfully: `target\debug\examples\calc.exe` (exit code: 0xcfffffff)

I just pulled today's master and ran all the examples again. It is only calc that hangs.

I noticed while testing open_save, that launching the win7 open and save windows from it has the white flash too. So I tried other applications calling those and it happens with all of them too.

So the white flash thing seems like it is due to this machine. If nobody else is experiencing it, the issue should probably be closed.

Regarding the hang, I adding logging into core.rs as the first line in each:

        log::debug!("impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn paint");
        log::debug!("impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn layout");
        log::debug!("impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event");
        log::debug!("impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle");
        log::debug!("impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn update");

That results in this:

cargo run --example calc
   Compiling druid v0.6.0 (C:\CODE\Rust\druid\druid)
    Finished dev [unoptimized + debuginfo] target(s) in 17.72s
     Running `target\debug\examples\calc.exe`
ERROR [druid_shell::platform::windows::util] No shcore.dll
ERROR [druid_shell::platform::windows::util] Could not load `GetDpiForSystem`. Windows 10 or later is needed
ERROR [druid_shell::platform::windows::util] Could not load `CreateDXGIFactory2`. Windows 8.1 or later is needed
DEBUG [druid::localization] available locales [], current en-US
DEBUG [druid::localization] resolved: [en-US]
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn lifecycle
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn update
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn event
DEBUG [druid::core] impl<T: Data, W: Widget<T>> WidgetPod<T, W> pub fn update
error: process didn't exit successfully: `target\debug\examples\calc.exe` (exit code: 0xcfffffff)

@xStrom
Copy link
Member

xStrom commented May 12, 2020

So the white flash thing seems like it is due to this machine. If nobody else is experiencing it, the issue should probably be closed.

Well you're just the only one who has reported it here. There can easily be lots of other people out there with the same issue. I would like to fix it.

The debug log you provided is promising. It shows that paint is never even reached. Could you run it again, but this time let's find out more about event.

let now = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap()
        .as_secs();
log::debug!("{} > {:?}", now, event);

This will help us understand what kind of events is it stuck dealing with.

@Adarma
Copy link
Author

Adarma commented May 12, 2020

ERROR [druid_shell::platform::windows::util] No shcore.dll
ERROR [druid_shell::platform::windows::util] Could not load `GetDpiForSystem`. Windows 10 or later is needed
ERROR [druid_shell::platform::windows::util] Could not load `CreateDXGIFactory2`. Windows 8.1 or later is needed
DEBUG [druid::localization] available locales [], current en-US
DEBUG [druid::localization] resolved: [en-US]
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowConnected
DEBUG [druid::core] 1589305894 > WindowSize(217.0W×275.0H)
DEBUG [druid::core] 1589305894 > WindowSize(217.0W×275.0H)
DEBUG [druid::core] 1589305894 > WindowSize(217.0W×275.0H)
DEBUG [druid::core] 1589305894 > WindowSize(217.0W×275.0H)
DEBUG [druid::core] 1589305894 > WindowSize(217.0W×275.0H)
DEBUG [druid::core] 1589305894 > WindowSize(217.0W×275.0H)
DEBUG [druid::core] 1589305894 > WindowSize(217.0W×275.0H)
DEBUG [druid::core] 1589305894 > WindowSize(217.0W×275.0H)
DEBUG [druid::core] 1589305894 > WindowSize(217.0W×275.0H)
DEBUG [druid::core] 1589305894 > WindowSize(217.0W×275.0H)
DEBUG [druid::core] 1589305894 > WindowSize(217.0W×275.0H)
DEBUG [druid::core] 1589305894 > WindowSize(217.0W×275.0H)
DEBUG [druid::core] 1589305894 > WindowSize(217.0W×275.0H)
error: process didn't exit successfully: `target\debug\examples\calc.exe` (exit code: 0xcfffffff)

I have since discovered that if I rename calc to calc2, it runs fine.
If I rename calc2 back to calc, the problem returns.

So I guess calc has something cached that is causing the issue.
I renamed the window title and cargo run it, and it still hangs, but with the new title.

I suspect a cargo clean will fix it, but I have not run that in case you want to investigate further.

@xStrom
Copy link
Member

xStrom commented May 12, 2020

Rust incremental builds sometimes go bad indeed, I've seen some crazy phantom behavior that is resolved by cargo clean. You should try that out.

@Adarma
Copy link
Author

Adarma commented May 12, 2020

Whatever caused the hang is gone now. Sorry about that tangent.
Back to the white flash...
I switched theme back to the Windows 7 default, but still see it.
File - Open in any program also has a brief white flash before the file explorer gui is drawn.

@xStrom
Copy link
Member

xStrom commented May 13, 2020

Okay, I created a branch with debug messages - xStrom/flash-debug.
https://github.com/xStrom/druid/tree/flash-debug

Run calc with that and then we can see which part is taking up the time.

@Adarma
Copy link
Author

Adarma commented May 13, 2020

I ran cargo run --example calc three times in a row from a newly cloned repo.
The first is after it complied everything.

   Compiling druid v0.6.0 (C:\CODE\Rust\flash\druid\druid)
    Finished dev [unoptimized + debuginfo] target(s) in 2m 11s
     Running `target\debug\examples\calc.exe`
ERROR [druid_shell::platform::windows::util] No shcore.dll
ERROR [druid_shell::platform::windows::util] Could not load `GetDpiForSystem`. Windows 10 or later is needed
ERROR [druid_shell::platform::windows::util] Could not load `CreateDXGIFactory2`. Windows 8.1 or later is needed
DEBUG [druid::localization] available locales [], current en-US
DEBUG [druid::localization] resolved: [en-US]
464.059918ms > WM_CREATE took 448.414587ms
465.304932ms > WM_SHOWWINDOW
55.546895ms > WM_SIZE took 65.635µs
paint.lifecycle took 18.049µs
paint.layout took 4.607166ms
paint.paint took 4.04968ms
73.873006ms > handler.paint took 12.169138ms
144.00892ms > WM_PAINT took 82.871974ms

/c/CODE/Rust/flash/druid ((9466e9a...))
$ cargo run --example calc
    Finished dev [unoptimized + debuginfo] target(s) in 1.37s
     Running `target\debug\examples\calc.exe`
ERROR [druid_shell::platform::windows::util] No shcore.dll
ERROR [druid_shell::platform::windows::util] Could not load `GetDpiForSystem`. Windows 10 or later is needed
ERROR [druid_shell::platform::windows::util] Could not load `CreateDXGIFactory2`. Windows 8.1 or later is needed
DEBUG [druid::localization] available locales [], current en-US
DEBUG [druid::localization] resolved: [en-US]
37.764325ms > WM_CREATE took 29.325716ms
38.154443ms > WM_SHOWWINDOW
20.484681ms > WM_SIZE took 74.66µs
paint.lifecycle took 14.768µs
paint.layout took 7.572638ms
paint.paint took 1.76312ms
32.763758ms > handler.paint took 10.981966ms
76.485689ms > WM_PAINT took 54.812193ms

/c/CODE/Rust/flash/druid ((9466e9a...))
$ cargo run --example calc
    Finished dev [unoptimized + debuginfo] target(s) in 0.72s
     Running `target\debug\examples\calc.exe`
ERROR [druid_shell::platform::windows::util] No shcore.dll
ERROR [druid_shell::platform::windows::util] Could not load `GetDpiForSystem`. Windows 10 or later is needed
ERROR [druid_shell::platform::windows::util] Could not load `CreateDXGIFactory2`. Windows 8.1 or later is needed
DEBUG [druid::localization] available locales [], current en-US
DEBUG [druid::localization] resolved: [en-US]
37.116178ms > WM_CREATE took 30.015703ms
39.004415ms > WM_SHOWWINDOW
36.771595ms > WM_SIZE took 94.35µs
paint.lifecycle took 10.665µs
paint.layout took 10.425709ms
paint.paint took 3.493833ms
71.964668ms > handler.paint took 34.782445ms
113.221595ms > WM_PAINT took 76.138234ms

@xStrom
Copy link
Member

xStrom commented May 13, 2020

Okay, that's useful. Thanks for doing the test runs!

It seems that the druid code parts aren't that slow. They work fast enough to deliver 60fps and are not the cause of the white flash.

As for what is slow, there seem to be two things.

  • WM_SIZE seems to take its sweet time showing up. It takes 20-55ms to show up after WM_SHOWWINDOW. On my Windows 7 machine it's always around 5ms.
  • Direct2D functionality seems to be slowish. What's your Windows graphics rating? You can see it under computer properties (Win+Pause hotkey) where you can click on "Windows experience index". Do you have a dedicated GPU or an integrated one? Are the drivers not older than a few years?

@Adarma
Copy link
Author

Adarma commented May 13, 2020

Its a company laptop, which I've been using for a few years. I doubt the drivers have been updated since it was first imaged, although updates are pushed out to it by the IT department.

image
image

It is running 3 monitors from a docking station, so I'll check tomorrow the performance with just the laptop screen on.

@xStrom
Copy link
Member

xStrom commented May 14, 2020

The specs aren't great but they should be good enough. I do also wonder if the multi-monitor situation has an effect, so that's worth checking out.

It's also worth testing if the flash also appears when you compile with --release. Could be useful to run my debug branch with the --release option to compare the timing numbers.

@Adarma
Copy link
Author

Adarma commented May 14, 2020

This was run with no monitors attached:

   Compiling druid v0.6.0 (C:\CODE\Rust\flash\druid\druid)
    Finished dev [unoptimized + debuginfo] target(s) in 1m 36s
     Running `target\debug\examples\calc.exe`
ERROR [druid_shell::platform::windows::util] No shcore.dll
ERROR [druid_shell::platform::windows::util] Could not load `GetDpiForSystem`. Windows 10 or later is needed
ERROR [druid_shell::platform::windows::util] Could not load `CreateDXGIFactory2`. Windows 8.1 or later is needed
DEBUG [druid::localization] available locales [], current en-US
DEBUG [druid::localization] resolved: [en-US]
42.403109ms > WM_CREATE took 38.511287ms
42.768622ms > WM_SHOWWINDOW
11.456819ms > WM_SIZE took 61.944µs
paint.lifecycle took 14.768µs
paint.layout took 7.977274ms
paint.paint took 4.074785ms
25.411509ms > handler.paint took 13.116597ms
67.881075ms > WM_PAINT took 56.173197ms

/c/CODE/Rust/flash/druid ((9466e9a...))
$ cargo run --example calc
    Finished dev [unoptimized + debuginfo] target(s) in 2.73s
     Running `target\debug\examples\calc.exe`
ERROR [druid_shell::platform::windows::util] No shcore.dll
ERROR [druid_shell::platform::windows::util] Could not load `GetDpiForSystem`. Windows 10 or later is needed
ERROR [druid_shell::platform::windows::util] Could not load `CreateDXGIFactory2`. Windows 8.1 or later is needed
DEBUG [druid::localization] available locales [], current en-US
DEBUG [druid::localization] resolved: [en-US]
32.078928ms > WM_CREATE took 27.141846ms
32.308245ms > WM_SHOWWINDOW
12.693653ms > WM_SIZE took 67.277µs
paint.lifecycle took 11.076µs
paint.layout took 6.274011ms
paint.paint took 2.040059ms
22.969428ms > handler.paint took 9.677664ms
56.335238ms > WM_PAINT took 43.118135ms

/c/CODE/Rust/flash/druid ((9466e9a...))
$ cargo run --example calc
    Finished dev [unoptimized + debuginfo] target(s) in 1.10s
     Running `target\debug\examples\calc.exe`
ERROR [druid_shell::platform::windows::util] No shcore.dll
ERROR [druid_shell::platform::windows::util] Could not load `GetDpiForSystem`. Windows 10 or later is needed
ERROR [druid_shell::platform::windows::util] Could not load `CreateDXGIFactory2`. Windows 8.1 or later is needed
DEBUG [druid::localization] available locales [], current en-US
DEBUG [druid::localization] resolved: [en-US]
26.734901ms > WM_CREATE took 22.44885ms
27.008112ms > WM_SHOWWINDOW
11.432205ms > WM_SIZE took 64.405µs
paint.lifecycle took 7.794µs
paint.layout took 4.208519ms
paint.paint took 4.325433ms
21.058591ms > handler.paint took 9.365481ms
58.686658ms > WM_PAINT took 47.108003ms

This is in --Release mode, also without monitors:

   Compiling druid v0.6.0 (C:\CODE\Rust\flash\druid\druid)
    Finished release [optimized] target(s) in 2m 45s
     Running `target\release\examples\calc.exe`
ERROR [druid_shell::platform::windows::util] No shcore.dll
ERROR [druid_shell::platform::windows::util] Could not load `GetDpiForSystem`. Windows 10 or later is needed
ERROR [druid_shell::platform::windows::util] Could not load `CreateDXGIFactory2`. Windows 8.1 or later is needed
DEBUG [druid::localization] available locales [], current en-US
DEBUG [druid::localization] resolved: [en-US]
380.742306ms > WM_CREATE took 376.097306ms
381.627165ms > WM_SHOWWINDOW
11.938425ms > WM_SIZE took 26.254µs
paint.lifecycle took 1.64µs
paint.layout took 3.365912ms
paint.paint took 929.985µs
17.797287ms > handler.paint took 5.421559ms
56.175659ms > WM_PAINT took 43.943511ms

/c/CODE/Rust/flash/druid ((9466e9a...))
$ cargo run --release --example calc
    Finished release [optimized] target(s) in 1.06s
     Running `target\release\examples\calc.exe`
ERROR [druid_shell::platform::windows::util] No shcore.dll
ERROR [druid_shell::platform::windows::util] Could not load `GetDpiForSystem`. Windows 10 or later is needed
ERROR [druid_shell::platform::windows::util] Could not load `CreateDXGIFactory2`. Windows 8.1 or later is needed
DEBUG [druid::localization] available locales [], current en-US
DEBUG [druid::localization] resolved: [en-US]
25.050919ms > WM_CREATE took 20.947009ms
25.482888ms > WM_SHOWWINDOW
10.569087ms > WM_SIZE took 14.358µs
paint.lifecycle took 1.231µs
paint.layout took 3.511953ms
paint.paint took 1.623268ms
19.080066ms > handler.paint took 7.06862ms
52.262094ms > WM_PAINT took 40.326541ms

/c/CODE/Rust/flash/druid ((9466e9a...))
$ cargo run --release --example calc
    Finished release [optimized] target(s) in 0.47s
     Running `target\release\examples\calc.exe`
ERROR [druid_shell::platform::windows::util] No shcore.dll
ERROR [druid_shell::platform::windows::util] Could not load `GetDpiForSystem`. Windows 10 or later is needed
ERROR [druid_shell::platform::windows::util] Could not load `CreateDXGIFactory2`. Windows 8.1 or later is needed
DEBUG [druid::localization] available locales [], current en-US
DEBUG [druid::localization] resolved: [en-US]
23.216384ms > WM_CREATE took 18.925411ms
23.709477ms > WM_SHOWWINDOW
10.310235ms > WM_SIZE took 31.177µs
paint.lifecycle took 1.23µs
paint.layout took 2.756315ms
paint.paint took 590.316µs
14.996257ms > handler.paint took 4.132216ms
51.468305ms > WM_PAINT took 40.674002ms

@xStrom
Copy link
Member

xStrom commented May 14, 2020

Looks like removing the monitors has a significant impact, and the release build also has some impact. Are you still seeing the white flash with --release and no monitors?

In general this looks like it has mostly to do with your specific setup. Like I mentioned earlier, the druid code here doesn't account for much. In these latest tests the druid code accouts for just 10% of the time it takes between the window showing and WM_PAINT finishing.

Something is making Windows/Direct2D slow and I'm not sure what it is.

@Adarma
Copy link
Author

Adarma commented May 15, 2020

Yes the white flash is still there without monitors and in release.
I think it is this machine too.
I copied the same exe to another Win7 machine and don't see it.

@xStrom xStrom removed the bug does not behave the way it is supposed to label May 15, 2020
@xStrom
Copy link
Member

xStrom commented May 15, 2020

Okay, I'll close this issue as there isn't anything we can change in druid to solve it right now.

@xStrom xStrom closed this as completed May 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
shell/win concerns the Windows backend
Projects
None yet
Development

No branches or pull requests

3 participants