Is paint() guaranteed to be called on the message thread?


#1

As the title says - in well-formed (i.e. not doing anything strange like arbitrarily calling paint() yourself) JUCE code, is paint() guaranteed to be called on the message thread regardless of the rendering backend?

In my scenario I’m trying to figure out if I need to implement some sort of FIFO to pipe data from my Timer based component’s timerCallback() to the repaint() triggered inside it.

In other words, if my timerCallback() calls repaint(), can I expect that paint() will be called before the next timerCallback(), since they’re all presumably getting queued on the message thread?


#2

AFAIK these are two different things. Calling repaint marks regions as dirty, and the OS will know then, that it would be good to call paint() now. However, if that really happens is up to the discretion of the OS. E.g. there was a couple of fine tuning involved a few OSX versions back for example, when the OS skipped paint() calls, when they occurred more often than 30 times per second, and all these kind of funnyness (I think that mentioned problem got resolved, but serves as example what can happen similary anytime).

So I would say: yes, it happens from the message thread and no, you can’t rely on that it actually painted anything…

I just put together my observations, please everybody correct me, if I’m wrong…


#3

Right, I know paint() events are getting queued to the OS and may be dropped, and may also happen in semi-random order (like if repaint() was called/queued off the message thread). I can deal with that, I suppose the more important of the questions is what thread the paint() is actually being called on.

I ran some tests and it seems the software and CoreGraphics renderers do paint on the message thread, though in the case of CoreGraphics I don’t know if that’s just a happy coincidence or if that’s deliberate. I’m aware of the fact that drawing _should_happen on the message thread as part of the program loop, but I still don’t feel confident in it given the arms race towards smooth animations and responsive apps combined with my somewhat lacking knowledge of native painting backends.

Similar story with the OpenGL backend, which I know uses a background rendering thread which makes me a little nervous - is the background thread there basically acting as a command buffer type of thing to defer the execution of the actual painting/drawing or what…?


#4

Doh, if only I had RTFM:

If you want to cause a component to redraw itself, this is done asynchronously - calling the repaint() method marks a region of the component as “dirty”, and the paint() method will automatically be called sometime later, by the message thread, to paint any bits that need refreshing. In Juce (and almost all modern UI frameworks), you never redraw something synchronously.

Seems like what I was looking for!