winterhell's picture

[solved] Switching windows focus slowdowns with GameWindow

Hi.
When I'm running an application with GameWindow and try to switch to another window I get a couple of seconds OS interface pause before the other window shows. The same thing happens when trying to get back to the GameWindow application, or minimizing/restoring it. It is more apparent when navigating with the taskbar rather than clicking on the actual window(which is impossible if you want Visual Studio/etc to be maximized). Also when starting the application it shows halfway on the taskbar and only after several seconds shows fully.

The problem is there on at least OpenTK 1.0 and 1.1 Beta 3, including the samples themselves.

I'm running Windows 7 64bit, GeForce GTX 650( on 660 Ti its the same), Visual Studio 2010.
Is this fixable?

If not, I'm willing to switch to GLControl, but would that compromise the portability to Linux and OS X?

Thanks.


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
winterhell's picture

Its not this, either. It breaks Basic Mouse Input, but GW Simple and GW MSAA still lag. This is on wgl_issue19.

When I put breakpoints at the beginning of the constructor and methods of abstract class WinInputBase : IInputDriver2, none seem to trigger, even at startup. Even on the Basic Mouse Input example.Is this because Example.exe call them them as an external process?

Oh and GLControl does not exhibit any issues here. Its probably because WindowsForms handles the events.

the Fiddler's picture

Oh, I thought the issue was reproducible on GLControl. Ok, so this leaves OpenTK.Platform.Windows.WinGLNative. It's either the window construction code or the message loop handler.

What happens if you modify line 153 like this?

                child_window = window;
                // previous code:
                //child_window = new WinWindowInfo(
                //    CreateWindow(
                //        0, 0, ClientSize.Width, ClientSize.Height,
                //        title, options, device, window.Handle),
                //    window);

If this doesn't help, then it's something inside the WindowProcedure function (line 244). Do you know if there are any tools that can monitor or trace WM_ messages flowing through the message loop?

Examples are launched in a separate process to protect against crashes, which is indeed why breakpoints don't work. What I usually do is run the example I'm interested in directly from Main.cs:

public static void Main()
{
    Examples.Tests.GameWindowStates.Main();
    return;
    ...
}

The example browser sucks so I'm going to remove it completely when I find the time. Separate example projects and a unit testing suite is the way forward.

winterhell's picture

When I modify the code, if I maximize the window its border disappears, starts from 0,0 and is much larger than the original, wider aspect ratio but covers less than 80% of the screen. When minimize/restore the same thing happens but the window this time takes 5-10% of the screen.
The triangle is rendered like usual.

Regardless of the change above, protected virtual IntPtr WindowProcedure
sends Unhandled events when I try to minimize/maximize or do anything really.

I dont know any such tools. It would probably be couple of pages of source code at most.

the Fiddler's picture

There is definitely something fishy going on in the WindowProcedure. This is some of the oldest code in OpenTK, with a lot of workarounds for system-specific issues found over the years. Reviewing this is going to take a while.

For instance, both the top-level and the child window are being routed through the same WindowProcedure. I do not know if this is safe.

At this point, the fastest solution might be to comment out the WindowProcedure (ignoring the side effects) until the problem stops happening. Once we localize the problem to a specific part of the WindowProcedure we should be able to find the solution.

I've located a system with a Nvidia 650 GPU, I'll see if I can reproduce the problem there.

winterhell's picture

Finding which functions get called during the events may help narrow it down.
Are there any classes outside Platform/Windows that might be connected?

the Fiddler's picture

OpenTK.GameWindow, which inherits from OpenTK.NativeWindow are the user-facing counterparts of WinGLNative. These are simple facades over the platform-specific code.

For example, GameWindow.WindowState works like this:

        public virtual WindowState WindowState
        {
            get
            {
                return implementation.WindowState;
            }
            set
            {
                implementation.WindowState = value;
            }
        }

Pretty much all user-facing methods, properties and events of GameWindow/NativeWindow are implemented like this, i.e. they simply forward themselves to a native "implementation". The "implementation" is a INativeWindow interface that is constructed at runtime (see OpenTK.Platform.Factory). On Windows, it resolves to an instance of OpenTK.Platform.Windows.WinGLNative. If you are using SDL2, then it goes to OpenTK.Platform.SDL2.Sdl2NativeWindow, etc.

When WinGLNative.WindowProcedure receives a message from the operating system, such as WindowMessage.SIZE, then it decodes the message and runs:

windowState = new_state;
WindowStateChanged(this, EventArgs.Empty);

If you hook GameWindow.WindowStateChanged then your application will be notified whenever the WindowState is changed.

There are similar events for keyboard/mouse input, window position, movement, style and state. The "GameWindowStates" example hooks most of these to inspect what is happening when it receives different events.

the Fiddler's picture

Ok, I made a fresh installation of Windows 7 64bit on a system with a Nvidia 650 Ti and I think I am seeing the problem you are describing. When I launch a GameWindow and try to minimize/restore through the taskbar, or alt-tab to a different application then restore through the taskbar, I get a few seconds of interface lag before the GameWindow responds.

Curiously, if I move or resize the window through its frame, then this issue goes away and does not return.

Something appears to be broken in the activation message handler. This should be fixable.

winterhell's picture

Yeah indeed resizing or moving fixes it.
Moving it however with
this.Location = new System.Drawing.Point(this.Location.X - 1, this.Location.Y);
does not.

the Fiddler's picture

More information here: https://github.com/opentk/opentk/issues/19

This issue appears to have something to do with IME handling.

the Fiddler's picture

This is solved in https://github.com/opentk/opentk/commit/2c14ec5f800b8ef6527f05ba26d6c6cc...

An explanation of the cause can be found here: The dangers of filtering window messages

Thanks a lot for your help in tracking down this issue!