+
+void Mixer::OutputChannel::output_frame(GLuint tex, RefCountedGLsync fence)
+{
+ // Store this frame for display. Remove the ready frame if any
+ // (it was seemingly never used).
+ {
+ std::unique_lock<std::mutex> lock(frame_mutex);
+ if (has_ready_frame) {
+ parent->release_display_frame(&ready_frame);
+ }
+ ready_frame.texnum = tex;
+ ready_frame.ready_fence = fence;
+ has_ready_frame = true;
+ }
+
+ if (has_new_frame_ready_callback) {
+ new_frame_ready_callback();
+ }
+}
+
+bool Mixer::OutputChannel::get_display_frame(DisplayFrame *frame)
+{
+ std::unique_lock<std::mutex> lock(frame_mutex);
+ if (!has_current_frame && !has_ready_frame) {
+ return false;
+ }
+
+ if (has_current_frame && has_ready_frame) {
+ // We have a new ready frame. Toss the current one.
+ parent->release_display_frame(¤t_frame);
+ has_current_frame = false;
+ }
+ if (has_ready_frame) {
+ assert(!has_current_frame);
+ current_frame = ready_frame;
+ ready_frame.ready_fence.reset(); // Drop the refcount.
+ has_current_frame = true;
+ has_ready_frame = false;
+ }
+
+ *frame = current_frame;
+ return true;
+}
+
+void Mixer::OutputChannel::set_frame_ready_callback(Mixer::new_frame_ready_callback_t callback)
+{
+ new_frame_ready_callback = callback;
+ has_new_frame_ready_callback = true;
+}
+