VSTGUI 3.6 Windows 7 GDI+ Sluggishness: A Workaround...

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

tony tony chopper wrote:if you get a wm_paint with a tiny invalidation rectangle, why would you prefer to repaint everything? If your source is a composite of lots of items, you can easily skip the items not hitting the invalidation rectangle.
well if you have a cache of the window, you actually just call bitblt with the rect as from the mw_paint message, then return. one message, one blit, return. as fast as possible. that's what i do. window tearing? what's that?

"animate?"

yes, animate. like when things move on the screen without user interaction, like meters or knobs or whatnot.
tony tony chopper wrote:redrawing windows is pretty bad, better invalidate it (or part of it) and let Windows deal with the messaging, delaying repaint messages when the message buffer is too crowded. I never ever grab a DC to paint in it directly.
oh but this is just your misconception. do you call invalidaterect? in which case you do grab a dc directly because you're just dispatching a message to yourself.
tony tony chopper wrote:the message.. is the whole point. As well as the region merging, when you invalidate rectangles that intersect.
you might want to check that is what actually happens, and not just an immediate wm_paint message that is forced to occur and operate before invalidaterect() will return.
tony tony chopper wrote:me too, and you don't refresh a game like you refresh a GUI.. You don't even process a game (cycle-based) like you process a normal app (msg-based, even though the msg loop is kind of a cycle).
i think nobody processes games or video cycle-based either, they instead use frame sync and drive video based upon frames. the main loop wouldn't want to interact with the video loop if you don't want to be dropping frames or lagging your game logic during heavy video activity... is that why so many games have such problems? (of course.)

you're saying we should force our guis to be delayed when something is happening in one or the other as well. do you think the window message dispatching is coated in magic pixie dust? open two child windows, lock the thread in one during a wm_paint and see if you can move the windows around and let them redraw as usual.

if so, maybe this is an improvement in vista/win7 that i haven't heard of yet.

when i say redraw as usual, i mean all three windows are still getting wm_paint and so on, and they're able to work as usual with all mouse messages.

in winxp - the main window will be dispatching the messages and the child windows will get them, and pass them onward down the chain. getmessage, translate, dispatch, etc. if a child window decides that instead of dispatching, it'll sleep(1000000), that should lock the entire host application.

are you using vstgui or did you write your own gui code? in a control in onMouse() call sleep(10000000) and see what happens. same deal because vstgui, my gui, everything works the same way. the messages are in a single thread.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

well if you have a cache of the window
..a cache that costed CPU to fully draw.. while you might not even have it all on screen.
Again, you keep saying that it happens often that things get asked to be repainted while their content hasn't changed, but I don't see why. Why would Windows do that, for what reasons?

yes, animate. like when things move on the screen without user interaction, like meters or knobs or whatnot.
I use invalidation for that, it's perfect. So that if the refresh rate is too high, it will just skip (& merge) some of the paint messages.

oh but this is just your misconception. do you call invalidaterect? in which case you do grab a dc directly because you're just dispatching a message to yourself.
invalidaterect uses a window, not DC. And yes I'm dispatching a message to myself, that's the whole point. WM_Paint is a special message not handled like others in the loop.
you might want to check that is what actually happens, and not just an immediate wm_paint message that is forced to occur and operate before invalidaterect() will return.
it's not. That's now SendMessage works, not PostMessage btw.

i think nobody processes games or video cycle-based either, they instead use frame sync and drive video based upon frames. the main loop wouldn't want to interact with the video loop if you don't want to be dropping frames or lagging your game logic during heavy video activity... is that why so many games have such problems? (of course.)
in my games the cycle was constant, whether it ended up drawing or skipping the frame, it was called at the same rate

do you think the window message dispatching is coated in magic pixie dust?
yes, read about wm_paint, google is your best friend
The system sends this message when there are no other messages in the application's message queue.
The system sends an internal WM_PAINT message only once. After an internal WM_PAINT message is returned from GetMessage or PeekMessage or is sent to a window by UpdateWindow, the system does not post or send further WM_PAINT messages until the window is invalidated or until RedrawWindow is called again with the RDW_INTERNALPAINT flag set.

In short, you tell Windows "invalidate this zone of this window". When Windows finds the time (no more msges in the loop), it processes that paint message. If in-between you also invalidated other zones of the window, Windows will have added that zone to the update region, and you still end up with 1 single paint message to process, only with a more complex invalidate region.
If I was doing a new OS-independent GUI system, I would still use the same method.
if so, maybe this is an improvement in vista/win7 that i haven't heard of yet.
it's as old as Win3.1
in winxp - the main window will be dispatching the messages and the child windows will get them, and pass them onward down the chain. getmessage, translate, dispatch, etc. if a child window decides that instead of dispatching, it'll sleep(1000000), that should lock the entire host application.
and if it chooses to crash, it will crash the host. What's your point?
DOLPH WILL PWNZ0R J00r LAWZ!!!!

Post

my point is - your application is locking up the host and you say it's a good thing.

do you know where windows merges these messages? translatemessage perhaps? either that or where they're added to the queue. either way it's in the same thread.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

my point is - your application is locking up the host and you say it's a good thing
are you not locking up the host when you repaint your cache? Even in another thread you will still be synchronizing/locking, even just so that the GUI isn't refreshing using what you're busy redrawing. Unless you use triple buffering (& thus waste even more memory)?

do you know where windows merges these messages?
when you invalidate a window
DOLPH WILL PWNZ0R J00r LAWZ!!!!

Post

sure, any redraw is locking the thread, but that's a lot less likely to be immediately when windows is trying to accomplish a redraw.

as i said, solved in vista/win7 if the hardware is used, great. not solved in xp.

i never redraw anything due to wm_paint unless the buffer is empty. outdated buffers are kept outdated and redrawn during my next timer update.

i just checked - actually i never redraw anything from wm_paint, ever. only a blit happens there.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

actually - ideally from the host's perspective you should only ever lock things up or update in idle().

that way, the host can measure how long idle calls are taking, and if they take too long it can adjust idle frequency downward, thereby controlling frame rate in plugins so that it does not interfere with window messaging. then you keep user interface responsiveness, even if the frame rate is reduced.

have they fixed vstgui's locking methods yet where a mouse click loops locked in the control and uses a "callback" to avoid locking the host? that of course is the stupidest implementation ever.

i like the idea of the host being able to manage plugins... what would you call that anyway? hosting?
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

have they fixed vstgui's locking methods yet where a mouse click loops locked in the control and uses a "callback" to avoid locking the host? that of course is the stupidest implementation ever.
at least we agree on something.
Such a bad implementation can only means it was a big noob programming it and that it should be avoided entirely.
DOLPH WILL PWNZ0R J00r LAWZ!!!!

Post

tony tony chopper wrote:
have they fixed vstgui's locking methods yet where a mouse click loops locked in the control and uses a "callback" to avoid locking the host? that of course is the stupidest implementation ever.
at least we agree on something.
Such a bad implementation can only means it was a big noob programming it and that it should be avoided entirely.
I think that as fixed years ago.

Post

i would hope so. i started to use vstgui for a couple months years ago until i realize it had such major problems, but by that time i had re-written major portions and my new code used the same method because i hadn't thought it through. once i wrote my own host i realized the callback thing was a ridiculous work-around and wasn't something excused by "it must be useful on the host side in some way" or similar.

only a couple years ago (shortly after the last xhip update) i re-wrote my code to use proper message handling so it would work easily on linux, because xt2's linux-vst implementation doesn't use callbacks at all.

when i wrote things years and years ago - in fact the very first gui i wrote used ordinary messaging, storing state and so on. isclicked, etc. vstgui's old implementation and the inclusion of the host idle callback just ruins vst - it should have been depreciated in vst2.4 but wasn't for some reason. i assumed vstgui still used it.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

Wow, a lot of useful information. Thanks guys! I totally forgot about this thread...
Works at KV331 Audio
SynthMaster voted #1 in MusicRadar's "Best Synth of 2019" poll
SynthMaster One voted #4 in MusicRadar's "Best Synth of 2019" poll

Post

aciddose wrote: i never redraw anything due to wm_paint unless the buffer is empty. outdated buffers are kept outdated and redrawn during my next timer update.

i just checked - actually i never redraw anything from wm_paint, ever. only a blit happens there.
How do you prevent the timer update repainting unnecessarily? It could get called multiple times between WM_PAINT messages, maybe more so if the system is under heavy load. So you could redraw multiple times but only blit the last redraw. And as you have little control over when you get WM_PAINT messages, you cant actually know whether a timer redraw will be wasted effort or not.

Also what do you do if a WM_PAINT message arrives and the timer thread is in the middle of a redraw? Blit the buffer as is? Or wait? Double buffer?

It really seems like it causes more problems than it solves to me.

Post

Our only hope is they kill each other. :hihi:

Just one little thing to add kv331. I haven't migrated to VSTGUI 3.6 yet (as I extensively subclassed an earlier version before the big refactoring, I'm now married to it) but for me, I got much better animation rates when I changed the line setting kIdleRate from 100 to 50 aeffguieditor.cpp

Nobody complains about chunky control movement since that change. Just FYI, not sure if it applies to your version or your issue.

Post

that's what I'm saying
DOLPH WILL PWNZ0R J00r LAWZ!!!!

Post

nollock wrote:How do you prevent the timer update repainting unnecessarily? It could get called multiple times between WM_PAINT messages, maybe more so if the system is under heavy load. So you could redraw multiple times but only blit the last redraw. And as you have little control over when you get WM_PAINT messages, you cant actually know whether a timer redraw will be wasted effort or not.

Also what do you do if a WM_PAINT message arrives and the timer thread is in the middle of a redraw? Blit the buffer as is? Or wait? Double buffer?

It really seems like it causes more problems than it solves to me.
1) limit frame-rate to below the display refresh rate (using the right flags, windows can frame-sync your blits if needed, but it isn't unless you only partially update an animation, which wouldn't make any sense)
2) wm_paint doesn't happen every frame anyway, so it's pointless to use this to meter anything
3) you don't need wm_paint at all, you can blit to the window and windows will always update on the next display refresh cycle - this should in most cases be done by hardware automatically these days
4) you're not supposed to control wm_paint, it's a notification that you _must_ fill in the window because the window manager's version of your data has been flushed or corrupted in some way (or for the initial call, doesn't exist)
5) since only a single blit occurs for each group of related elements, and the buffer is always therefore in it's "up to date" state, what's shown on the screen can never be invalid or partially drawn. what if wm_paint occurs during the blit? i'm not sure if windows allows that or how it's handled if you're inside a blit while a redraw occurs - if it causes corruption i've never seen it, and if i had to fix it only a mutex could take care of that where you'd refuse to do anything in wm_paint if a blut was taking place already.

it doesn't cause any problems for me at all.

regarding #3, what about if the user turns off the display? how does your application keep track of that wasted drawing? :hihi:
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

I'm sure you do know yourself that it's not the proper way to refresh stuff in Windows. You're not checking if the control is visible either? Nor if the GUI is visible or hidden (I hope you do, because your GUI will be hidden more than visible in a sequencer)?
DOLPH WILL PWNZ0R J00r LAWZ!!!!

Post Reply

Return to “DSP and Plugin Development”