Skip to content

FrameSetBarrier.kt

src/jvmMain/kotlin/afield/graphics/texture/video/FrameSetBarrier.kt · 63 lines

Holds back presentation of a frame set until every member is ready, so several textures switch frames together.

Ordinary clock ticks cannot replace an unfinished set; a new seek or reconfiguration revision can. FrameSetBarrierTest covers it.

package afield.graphics.texture.video

class FrameSetBarrier<K : Any>

Nonblocking two-phase presentation. Ordinary clock ticks cannot supersede an unfinished set (which would starve a slow decoder); an explicit seek/reconfiguration revision can. Call from one render thread. K must be an immutable source-frame identity.

class FrameSetBarrier<K : Any> {

var pending: K?

The frame identity select is holding back, or null when nothing is waiting. It survives ordinary clock ticks, and is cleared by presentIfReady, by revise with a new revision, or by reset.

    var pending: K? = null
        private set

var presented: K?

The frame identity the set is showing, or null before the first one. presentIfReady moves pending here once its upload callback has returned, so this names images the caller has committed to rather than ones it has asked for.

    var presented: K? = null
        private set
    private var revision: Long? = null

fun select(desired: K, revision: Long): K?

    fun select(desired: K, revision: Long): K? {
        revise(revision)
        if (pending == null && desired != presented) pending = desired
        return pending
    }

fun revise(revision: Long)

Cancel stale pending work even when a paused pacer has no replacement key to select.

    fun revise(revision: Long) {
        if (this.revision == revision) return
        pending = null
        this.revision = revision
    }

fun presentIfReady(ready: (K) -> Boolean, upload: (K) -> Unit): Boolean {

No upload callback runs until the whole set is ready. Commit only after uploads succeed.

    fun presentIfReady(ready: (K) -> Boolean, upload: (K) -> Unit): Boolean {
        val key = pending ?: return false
        if (!ready(key)) return false
        upload(key)
        presented = key
        pending = null
        return true
    }

fun reset()

    fun reset() {
        pending = null
        presented = null
        revision = null
    }
}