Repaint synchronisation on MacOS


#1

Given two calls to repaint during the same callback from the message loop there’s no reason why the paint calls would happen at different times? I’ve got two channels of audio and sometimes one gets ahead of the other when scrolling, zooming or recording. And both channels are listeners to the same transport information, they both call repaint when the transport (or view position) moves, and then one moves before the other … grrr :slight_smile:


#2

I’m afraid the way that dirty regions are merged (or not) into repaint callbacks is down to the rendering engine, so if you’re using CoreGraphics or Windows then it’s the OS making the decisions there.

If you use the engines like openGL where it’s JUCE code handling the invalidation messages then I think they do definitely make sure that a single repaint includes all the currently dirty rectangles.


#3

Ah right, I hadn’t realised the openGL one woudl do anything different. I’ll try that and see if it fixes it. If it does maybe I’ll do something horrible to consolidate the messages into one before telling OSX.

In happier news my waveform updating is down to <2% of a core now :slight_smile:


#4

care to share how you got that awesome stat?


#5

Really small window, liquid nitrogen on the CPU.


#6

More seriously … by passing information about where the updated content is to the repaint call and then only updating tiny parts of the screen in the paint method (and therefore only looking in a tiny portion of a summary file or WAV file for the waveform data).

MacOS really fucks it up if i have two cursors on the screen moving though by consolidating the repaint into a bigger single rectangle. But I think I could save my own dirty list and use an image to sort that out if it becomes a problem (and most of the time the user doesn’t have multiple cursors moving).


#7


#8


#9

Seemed to do the trick:

void newDataToPaint (double startPosition, double endPosition) override
{
    auto x1 = roundToInt(controller.getXForPos(getWidth(), startPosition));
    auto x2 = roundToInt(controller.getXForPos(getWidth(), endPosition));

    if (x1 > x2)
        std::swap(x1, x2);

    repaint(x1 - 1, 0, x2 - x1 + 1, getHeight());
}