VBlankAttachment and how does it work?

Can someone who knows a bit about this explain this one.

My knowledge is like this…

So your monitor has some refresh rate.

VBlankAttachment triggers a call on some callback at the refresh rate, and when? Immediately after the previous display refresh.

And then you call repaint().

This tells the OS you wanna repaint, so it calls back via ComponentPeer and your paint method gets called.

And this is guaranteed, or likely to happen before the next refresh happens?

It’s all a bit of a mystery :slight_smile:

I think of it as as way to prepare data between paint calls. You can repaint using a timer and just do changes to the data in vblank callback, or just use the vblank callback to do the repaint call.

This also means you can use it to avoid paint calls if the data hasnt changed, so its like a nice way to check if its worth doing each callback.

Good question, I always think of this as as “a hook right before the next paint() call propagates down from the peer to your components.” So maybe “immediately before the next refresh” or “on next refresh” is more accurate (depending on the implementation).

Reading code again, vblank callbacks fire right right before the OS is notified about what’s dirty, it’s clearest on windows:

    void onVBlank() override
    {
        vBlankListeners.call ([] (auto& l) { l.onVBlank(); }); // your callbacks, if any
        dispatchDeferredRepaints(); // tell the os to invalidate rects

        if (renderContext != nullptr)
            renderContext->onVBlank(); // D2D calls peer.handlePaint()
    }

So basically, it’s a “last chance” for a component to mark itself as dirty (via repaint) right before the cascade of paint calls happen.

Inside the vblank callback, I often just test if a boolean has changed (for example a parameter changed which means a visualization needs to change, or animation is running) and then call repaint(). I do treat it as guaranteed to be repainted on the next OS paint, but I haven’t “proven” this empirically.

I’m less clear on the exact mechanism on macOS, but it seems to be an AsyncUpdater calling the onVBlank, and that’s all wired up to a CVDisplayLink which is an OS notification that a paint is about to happen. This part seems like magic to me!