egui icon indicating copy to clipboard operation
egui copied to clipboard

Regarding severe graphical glitches with egui

Open rustbasic opened this issue 2 years ago • 5 comments

Title: Regarding severe graphical glitches with egui

Dear emilk,

When continuously running a program that uses the egui library on windows, there is a bug causing severe graphic glitches after about 1 to 6 hours.

Before I explain the circumstances leading to this glitch, I want to highlight another bug.

        frame.set_minimized(true);

When using the above function or the native windows minimize button and then restoring the program to its original size, the frame.info().window_info.minimized remains constantly set to true. Therefore, it's impossible to determine whether the program is in a minimized state. In the minimized state, ui.available_width() slightly decreases, and ui.available_height() becomes 0.0. After restoring from the minimized state, while ui.available_width() returns to normal, sometimes ui.available_height() remains at 0.0.

I've tried to determine the exact conditions that lead to the graphic glitches. The frequency of glitches appears to be higher when restoring the program to its original size after minimizing it for over an hour. The graphical glitches also occur every few hours even without minimizing the program. When these glitches happen, it seems ui.available_height() is at 0.0. It's presumed that the glitches might be linked to the instances when, upon restoring from minimized state, ui.available_height() occasionally remains at 0.0.

Please note that this behavior isn't consistent, as it happens only every few hours. However, these are my observations so far while trying to reproduce and prevent this glitch.

Thanks.


egui Version egui 0.22.0 egui 0.21.0

[ BUG Capture ] https://github.com/rustbasic/rdesk/blob/main/bug-capture-1.jpg?raw=true

[ No Bug Capture ] https://github.com/rustbasic/rdesk/blob/main/no-bug-capture-1.jpg?raw=true


Dear emilk,

I've been working for over 6 months to reproduce the issue of graphics breaking every few hours in a Windows program using the egui library. Through these efforts, I've roughly identified the reason and found a temporary way to prevent it.

When the program is minimized, the value of ui.available_height() decreases.

In the minimized state, the value of ui.available_height() seems to range between 0.0 to 20.0, depending on where the program was launched.

I tried using the method if ui.available_height() < 100.0 { return; }, but graphics still broke every few hours when restoring from a minimized state.

So,

let mut ui_available_height = ui.available_height();
if ui_available_height < 100.0 {
    ui_available_height = ui_available_height.at_least(100.0);
}

I created the ui_available_height value using the above method and used it, but still, the graphics broke every few hours after restoring from a minimized state.

Lastly, I found a method where graphics didn't break for 2-3 days upon testing.

fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
    ...
    let mut minimized_stop_work = false;
    ...
    egui::CentralPanel::default().frame(panel_frame).show(ctx, |ui| {
        let ui_available_height = ui.available_height();
        if ui_available_height < 100.0 {
            minimized_stop_work = true;
        }
        ...
    });     // CentralPanel()
    ...
    if !minimized_stop_work {
        ctx.request_repaint();
    }
}    // fn update()

By assuming that it's in a minimized state when ui.available_height() is below 100.0, and by not executing ctx.request_repaint(); (RunMode::Continuous mode in egui_demo_app.exe), the screen doesn't break even when restoring from a minimized state in Windows for a prolonged period. I've successfully tested this for 2-3 days.

This method might temporarily prevent the screen from breaking. However, I'm looking forward to a fundamental solution provided by the egui library.

Thanks, emilk.

rustbasic avatar Sep 08 '23 06:09 rustbasic

Dear emilk,

I've been working for over 6 months to reproduce the issue of graphics breaking every few hours in a Windows program using the egui library. Through these efforts, I've roughly identified the reason and found a temporary way to prevent it.

When the program is minimized, the value of ui.available_height() decreases.

In the minimized state, the value of ui.available_height() seems to range between 0.0 to 20.0, depending on where the program was launched.

I tried using the method if ui.available_height() < 100.0 { return; }, but graphics still broke every few hours when restoring from a minimized state.

So,

let mut ui_available_height = ui.available_height();
if ui_available_height < 100.0 {
    ui_available_height = ui_available_height.at_least(100.0);
}

I created the ui_available_height value using the above method and used it, but still, the graphics broke every few hours after restoring from a minimized state.

Lastly, I found a method where graphics didn't break for 2-3 days upon testing.

fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
    ...
    let mut minimized_stop_work = false;
    ...
    egui::CentralPanel::default().frame(panel_frame).show(ctx, |ui| {
        let ui_available_height = ui.available_height();
        if ui_available_height < 100.0 {
            minimized_stop_work = true;
        }
        ...
    });     // CentralPanel()
    ...
    if !minimized_stop_work {
        ctx.request_repaint();
    }
}    // fn update()

By assuming that it's in a minimized state when ui.available_height() is below 100.0, and by not executing ctx.request_repaint(); (RunMode::Continuous mode in egui_demo_app.exe), the screen doesn't break even when restoring from a minimized state in Windows for a prolonged period. I've successfully tested this for 2-3 days.

This method might temporarily prevent the screen from breaking. However, I'm looking forward to a fundamental solution provided by the egui library.

Thanks, emilk.

rustbasic avatar Sep 23 '23 06:09 rustbasic

Thanks for your investigation!

First of all: your posts are easier to read if you add proper markdown code blocks.

You should be able to read the minimized state with frame.info().window_info.minimized instead of checking for the available height.

The question is what eframe should do when an app is minimized. I think it should still call App::update, but giving a very small available_height seems the wrong thing to do, and sounds like a bug in eframe, or perhaps winit.


We should also consider splitting App::update into two: one App::tick and one App::ui. tick would be called even when minimized, while ui only when non minimized (right after the call to tick).

emilk avatar Sep 23 '23 13:09 emilk

Dear emilk,

In egui v0.22.0, the value of Frame.info().window_info.minimized seems to be inconsistent, making it unusable. It (= my program) always calls ctx.request_repaint() in the same manner as RunMode::Continuous.

    if !minimized_stop_work {
        ctx.request_repaint();
    }

Using this approach, I haven't experienced any screen corruption for several days.

Thanks emilk.

rustbasic avatar Sep 23 '23 14:09 rustbasic

Dear emilk,

I would like to share the results of using egui v0.24.0 ( & v024.1 ) on Windows for the past few days. I encountered one scene where the screen broke, and the program terminated within 3 seconds. Instead of the screen breaking, when used in a minimized state for approximately 2 to 6 hours, the program often exits. However, this is a better outcome than the screen breaking, as when the screen breaks, the program becomes unusable, and it is difficult to terminate.

In versions prior to egui v0.23.0, the screen often remained in a broken state. With egui v0.24.0, there were no instances where the screen continued to be in a broken state.

I would like to determine if the window is in a minimized state using the winapi::um::winuser::IsIconic() function. However, as the HWND of the window in egui is in a private state, there is no way to know if it is in a minimized state.

pub fn is_minimized() -> bool {

    let foreground_window: *mut winapi::shared::windef::HWND__ = unsafe { winapi::um::winuser::GetForegroundWindow() };
    let is_minimized: bool = unsafe { winapi::um::winuser::IsIconic(foreground_window) } != 0;

    return is_minimized;
}

Still assuming that the window is in a minimized state if the window size is less than 100.0, and not requesting repaint during the minimized state, the program works fine. (I have also made sure not to output other screens of the viewpoint during the minimized state.)

Copy code
let ui_available_height = ui.available_height();
if ui_available_height < 100.0 {
    minimized_stop_work = true;
}

if !minimized_stop_work {
    ctx.request_repaint();
}

This is an update sharing the current usage experience.

Thanks, emilk.

rustbasic avatar Dec 09 '23 10:12 rustbasic

P.S. I didn't mention one observed point. When the program exits in a minimized state, the screen briefly flickers (within 0.1 seconds), appearing and disappearing, before the program terminates.

rustbasic avatar Dec 09 '23 10:12 rustbasic