#pragma once #include "GLExtensions.h" #include "VideoIOTypes.h" #include #include #include class OpenGLRenderer; class RuntimeHost; struct RenderPipelineFrameContext { VideoIOState videoState; VideoIOCompletion completion; }; class OpenGLRenderPipeline { public: using RenderEffectCallback = std::function; using OutputReadyCallback = std::function; using PaintCallback = std::function; OpenGLRenderPipeline( OpenGLRenderer& renderer, RuntimeHost& runtimeHost, RenderEffectCallback renderEffect, OutputReadyCallback outputReady, PaintCallback paint); ~OpenGLRenderPipeline(); bool RenderFrame(const RenderPipelineFrameContext& context, VideoIOOutputFrame& outputFrame); private: struct AsyncReadbackSlot { GLuint pixelPackBuffer = 0; GLsync fence = nullptr; std::size_t sizeBytes = 0; bool inFlight = false; }; bool EnsureAsyncReadbackBuffers(std::size_t requiredBytes); void ResetAsyncReadbackState(); void FlushAsyncReadbackPipeline(); void QueueAsyncReadback(const VideoIOState& state); bool TryConsumeAsyncReadback(VideoIOOutputFrame& outputFrame, GLuint64 timeoutNanoseconds); void CacheOutputFrame(const VideoIOOutputFrame& outputFrame); void ReadOutputFrameSynchronously(const VideoIOState& state, void* destinationBytes); void PackOutputFor10Bit(const VideoIOState& state); void ReadOutputFrame(const VideoIOState& state, VideoIOOutputFrame& outputFrame); OpenGLRenderer& mRenderer; RuntimeHost& mRuntimeHost; RenderEffectCallback mRenderEffect; OutputReadyCallback mOutputReady; PaintCallback mPaint; std::array mAsyncReadbackSlots; std::size_t mAsyncReadbackWriteIndex = 0; std::size_t mAsyncReadbackReadIndex = 0; std::size_t mAsyncReadbackBytes = 0; GLenum mAsyncReadbackFormat = GL_BGRA; GLenum mAsyncReadbackType = GL_UNSIGNED_INT_8_8_8_8_REV; GLuint mAsyncReadbackFramebuffer = 0; std::vector mCachedOutputFrame; };