Skip to content

Win32 window resizing doesn't draw new frames #1293

@AnyOldName3

Description

@AnyOldName3

As discussed a few days ago, resizing the window on Windows is supposed to continue drawing frames during the resize, but doesn't, and instead, the last frame just gets bilinearly scaled to fit the window until the mouse is released.

I've done some investigation, and the reason for the current behaviour is that the default window message handlers aren't leaving the stack until the resize has finished. That means that the resize events just get queued up in a buffer and then all happen in quick succession between frames. That's particularly bad as each of the buffered resize events triggers regeneration of all pipelines, and those new pipelines will go unused except for the final resize, although with #1268 or equivalent, that would stop happening.

If we were to do things by the book, then instead of having the current

        while (viewer->advanceToNextFrame())
        {
            viewer->handleEvents();
            viewer->update();
            viewer->recordAndSubmit();
            viewer->present();
        }

main loop, we'd have something more like Win32_Window.cpp's

    while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
    {
        if (msg.message == WM_QUIT)
        {
            // somehow close all windows
            events.emplace_back(vsg::CloseWindowEvent::create(this, event_time));
        }
        else
        {
            TranslateMessage(&msg);
            DispatchMessageW(&msg);
        }
    }

and all the calls to the viewer would be done in response to a WM_PAINT message.

Windows is sending a WM_PAINT message several times during a resize to tell us to draw a new frame, but because the viewer->handleEvents() call hasn't returned, we can't.

For comparison, I checked what the OSG did, and its behaviour was arguably worse - it didn't do the bilinear scaling, but did still stop rendering frames, so you'd end up with this ugly mess:
image

vsgQt's vsgqtviewer avoids the problem because it basically doesn't use a typical VSG main loop, instead letting Qt have control over the main loop. Qt internally has something relatively similar to a by-the-book Win32 window event pump as its main loop, and fits its own work within it, e.g. interleaving the timer event that triggers a redraw into its event queue.

I'll look into ways to solve this and hope there'll be something that doesn't require the message pump to become the main loop.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions