Infinite Window

86c043eaa94314399cc064d153a93d26
0
_NOISEcore 101 Sep 27, 2011 at 19:44

Hi there.

I often create little projects, and I at the moment I have a basic window creation & message loop (handling) set up.
But often, my message loops result in the “infinite window” bug when
moving the window. This is just minor of course, but this always bugs me out.

Does anybody know what actually causes this? Is it because I’m not
double buffering yet?

Here’s a link to a screenshot if you don’t know what I mean with the “Infinite Window” bug.

http://imageshack.us/photo/my-images/714/infinitewindow.jpg/

21 Replies

Please log in or register to post a reply.

6eaf0e08fe36b2c23ca096562dd7a8b7
0
__________Smile_ 101 Sep 27, 2011 at 21:05

Do you have any wait function in your message loop? Maybe your application eats all CPU and other applications doesn’t have required processor power to redraw windows?

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Sep 27, 2011 at 22:53

Indeed. Can you post the code for your message loop?

86c043eaa94314399cc064d153a93d26
0
_NOISEcore 101 Sep 28, 2011 at 00:54

Well, atm it’s a very basic message loop. I need to add a timer when I get up in the morning :)

MSG msg = {};
    while(msg.message != WM_QUIT)
    {
        // Send the message if one is found
        if(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Sep 28, 2011 at 01:02

Well, there’s your problem! PeekMessage doesn’t wait if there’s no message available, so your app just sits in that tight loop taking up 100% CPU and not giving the other apps much chance to run. ;)

It doesn’t look like you’re doing any rendering yet. Once you do, you’ll presumably be waiting on vsync at the end of rendering, so this problem will go away. You could also put a Sleep(0) call in the loop, although it’s probably not good to have that in there long-term.

86c043eaa94314399cc064d153a93d26
0
_NOISEcore 101 Sep 28, 2011 at 01:06

Yeah, basically how I usually do it, I set an if else loop, where in the if it checks for a message, if none is found, it checks if the minimum time for a frame (max frame cap) has elapsed yet and renders/thinks if so.

Will this make the “infinite window” go away? Because usually when I get to that point in programming, I already use a fullscreen (which I won’t in this program)

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Sep 28, 2011 at 01:53

Well, what does it do if the minimum time for a frame *hasn’t* elapsed yet? If you do a Sleep(0) or something in that case, you should be fine, as you’ll yield the rest of your time-slice back to the OS. But if you just sit in a loop and don’t do anything that suspends the thread, you’ll keep taking up 100% CPU and making it hard for anything else to run.

IMO, the right way to do this is to configure your rendering API to wait for vsync, and if the API is built properly this should suspend the thread until the vsync clears, which will have the side effect of reducing the CPU utilization to a more reasonable level.

For reference, here’s my message loop:

MSG msg;
while (true)
{
    if (g_fRendering)
    {
        Update();
        Render();

        while (g_fRendering && PeekMessage(&msg, NULL, 0, 0, true))
            DispatchMessage(&msg);
    }
    else
    {
        if (!GetMessage(&msg, NULL, 0, 0))
            break;
        DispatchMessage(&msg);
    }
}

The g_fRendering flag gets set to false when you minimize the app, or when it starts shutting down; in that case I use GetMessage, which waits for a message, rather than PeekMessage. Down inside the Render() call I’m eventually calling Present() (since I’m using D3D) and telling it to wait for vsync, which both prevents tearing (usually…) and suspends the thread so that other apps can run.

It’s also important to handle *all* available messages after each rendered frame, not just one, hence the PeekMessage in the inner while loop. Otherwise messages can back up and overflow the queue because you don’t process them fast enough. Mouse moves especially can generate several messages per frame.

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Sep 28, 2011 at 10:58

What I usually do is using SetTimer() to let Windows post a WM_TIMER to my message queue every x milliseconds (the minimum is 10, which gives you 100 messages per second), and then do my rendering in response to a WM_TIMER. Automatic frame limiter ;)

86c043eaa94314399cc064d153a93d26
0
_NOISEcore 101 Sep 28, 2011 at 14:37

@Reedbeta

The g_fRendering flag gets set to false when you minimize the app, or when it starts shutting down; in that case I use GetMessage, which waits for a message, rather than PeekMessage. Down inside the Render() call I’m eventually calling Present() (since I’m using D3D) and telling it to wait for vsync, which both prevents tearing (usually…) and suspends the thread so that other apps can run. It’s also important to handle *all* available messages after each rendered frame, not just one, hence the PeekMessage in the inner while loop. Otherwise messages can back up and overflow the queue because you don’t process them fast enough. Mouse moves especially can generate several messages per frame.

If you do this, how would you then set in a frame limiter? Would you do that inside the scope where Update & Render get called?

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Sep 28, 2011 at 14:49

No, I would do that in the message loop itself. Calculate how much time there’s left before you want to do another frame, and use MsgWaitForMultipleObjects() to wait for a message with a timeout, and use as the timeout the time until the next frame you just calculated.

But as said, I would just stick to SetTimer(), it makes your code clean and simple.

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Sep 28, 2011 at 16:59

@_NOISEcore

If you do this, how would you then set in a frame limiter? Would you do that inside the scope where Update & Render get called?

Frame limiting is taken care of by the vsync. I don’t have a need to limit to some arbitrary rate like 100 fps; I only ever want to run at the refresh rate (or divisors thereof).

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Sep 28, 2011 at 17:09

Some people turn off vsync. You’d better still have some other means to limit the framerate available as well. Besides, there is no vsync in windowed mode.

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Sep 28, 2011 at 18:10

@.oisyn

Besides, there is no vsync in windowed mode.

Uhm…what? ;) I’m using vsync just fine in windowed mode in my own Direct3D app…

86c043eaa94314399cc064d153a93d26
0
_NOISEcore 101 Sep 28, 2011 at 18:36

Well, the problem is that I’m currently working on a little project for school (sort of) that tries to make as much use of GDI as possible.

So I don’t really have access to VSYNC (I think), in which I just switch to limiting the framerate to the refresh rate of the screen (or more if desired)

That’s why I need to implement the timer :)

6eaf0e08fe36b2c23ca096562dd7a8b7
0
__________Smile_ 101 Sep 28, 2011 at 19:36

For simple game you don’t need to redraw every frame (for tetris you must redraw on button press & timer tick only). Put you drawing code in WM_PAINT handler (together with ValidateRect if needed) and call InvalidateRect when you need to update window contents.

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Sep 28, 2011 at 21:39

@Reedbeta

Uhm…what? :huh: I’m using vsync just fine in windowed mode in my own Direct3D app…

It appears that you are right. I don’t know where I got this from ;)

86c043eaa94314399cc064d153a93d26
0
_NOISEcore 101 Sep 29, 2011 at 09:50

@’

‘]For simple game you don’t need to redraw every frame (for tetris you must redraw on button press & timer tick only). Put you drawing code in WM_PAINT handler (together with ValidateRect if needed) and call InvalidateRect when you need to update window contents.

I actually haven’t thought of that. I still need alot of “lessons” on effeciency :)
Thank you !

EDIT: I do have an additional problem atm. Well 2, concerning the same things.
First of all, my message loop looks like this:

        MSG msg = {};
    while(msg.message != WM_QUIT)
    {
        if(m_bActive)
        {
            // If the window is active

            while(m_bActive && PeekMessage(&msg,NULL,0,0,PM_REMOVE))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }

            Sleep(0);
        }
        else
        {
            if(!GetMessage(&msg,NULL,0,0))
                break;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

The problem is, m_bActive gets set to false when WM_ACTIVATE with wParam being WA_INACTIVE, and else it gets set back to true.
When I click away, this works, but when I just minimize it keeps using thesame CPU amount as when activated.

This comes to my second problem, at the moment my program doesn’t do that much, but yet it uses 25% of my CPU (dual core so..)
This is probably because of me not returning the remainder of my time slice, but I don’t know how to do this. They say with Sleep(0)
but this doesn’t seem to do anything.

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Sep 29, 2011 at 11:01

Please, don’t resort to Sleep(0), it’s bad practice for the purpose you’re using it for.

hey say with Sleep(0) but this doesn’t seem to do anything.

It does, but if there’s no other process who wants CPU time it still goes to your app.

86c043eaa94314399cc064d153a93d26
0
_NOISEcore 101 Sep 29, 2011 at 14:32

If sleep is a bad practice, what should I use then? MsgWaitForMultipleObjects ?

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Sep 29, 2011 at 14:47

I’m not saying Sleep is bad practice, I was talking about Sleep(0). You don’t want to just give up the remainded of the time slice, you want to wait until it’s time for the next frame. So you should calculate how long you’d like to wait.

And you can implement the wait with Sleep(), but the downside is that you’re unable to process messages when you’re sleeping. So MsgWaitForMultipleObjects() is, in my opinion, the better choice.

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Sep 29, 2011 at 16:21

@_NOISEcore

When I click away, this works, but when I just minimize it keeps using thesame CPU amount as when activated.

You’ll need to trap WM_SIZE as well as WM_ACTIVATE, and check for wParam being SIZE_MINIMIZED.

86c043eaa94314399cc064d153a93d26
0
_NOISEcore 101 Sep 29, 2011 at 17:17

@Reedbeta

You’ll need to trap WM_SIZE as well as WM_ACTIVATE, and check for wParam being SIZE_MINIMIZED.

This does not seem to do the trick. But I’ll look into that later :)

However, I still have the issue that apparently Sleep(0) doesn’t do anything (still uses 25%) and so does MsgWaitForMultipleObjects, however, Sleep(1) does reduce it greatly (0 or 1%) but cuts my framerate in half.