public override void RenderPixelBuffer(CoreVideo.CVPixelBuffer destinationPixelBuffer, CoreVideo.CVPixelBuffer foregroundPixelBuffer, CoreVideo.CVPixelBuffer backgroundPixelBuffer, float tween) { EAGLContext.SetCurrentContext(CurrentContext); if (foregroundPixelBuffer == null && backgroundPixelBuffer == null) { return; } var foregroundLumaTexture = LumaTextureForPixelBuffer(foregroundPixelBuffer); var foregroundChromaTexture = ChromaTextureForPixelBuffer(foregroundPixelBuffer); var backgroundLumaTexture = LumaTextureForPixelBuffer(backgroundPixelBuffer); var backgroundChromaTexture = ChromaTextureForPixelBuffer(backgroundPixelBuffer); var destLumaTexture = LumaTextureForPixelBuffer(destinationPixelBuffer); var destChromaTexture = ChromaTextureForPixelBuffer(destinationPixelBuffer); GL.UseProgram(ProgramY); // Set the render transformq float[] preferredRenderTransform = { (float)RenderTransform.xx, (float)RenderTransform.xy, (float)RenderTransform.x0, 0.0f, (float)RenderTransform.yx, (float)RenderTransform.yy, (float)RenderTransform.y0, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; GL.UniformMatrix4(Uniforms [(int)Uniform.Y], 1, false, preferredRenderTransform); GL.BindFramebuffer(FramebufferTarget.Framebuffer, (int)OffscreenBufferHandle); GL.Viewport(0, 0, (int)destinationPixelBuffer.GetWidthOfPlane(0), (int)destinationPixelBuffer.GetHeightOfPlane(0)); // Y planes of foreground and background frame are used to render the Y plane of the destination frame GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(foregroundLumaTexture.Target, foregroundLumaTexture.Name); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.ClampToEdge); GL.ActiveTexture(TextureUnit.Texture1); GL.BindTexture(backgroundLumaTexture.Target, backgroundLumaTexture.Name); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.ClampToEdge); GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferSlot.ColorAttachment0, destLumaTexture.Target, destLumaTexture.Name, 0); if (GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != FramebufferErrorCode.FramebufferComplete) { Console.WriteLine("Failed to make complete frmaebuffer object: " + GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer).ToString()); foregroundLumaTexture.Dispose(); foregroundChromaTexture.Dispose(); backgroundLumaTexture.Dispose(); backgroundChromaTexture.Dispose(); destLumaTexture.Dispose(); destChromaTexture.Dispose(); // Periodic texture cache flush every frame VideoTextureCache.Flush(CoreVideo.CVOptionFlags.None); EAGLContext.SetCurrentContext(null); } GL.ClearColor(0f, 0f, 0f, 1f); GL.Clear(ClearBufferMask.ColorBufferBit); float[] quadVertexData1 = { -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, }; // Compute the vertex data for the foreground frame at this instructionLerp quadVertexCoordinates(ref quadVertexData1, ForegroundTrack, tween); // texture data varies from 0 -> 1, whereas vertex data varies from -1 -> 1 float[] quadTextureData1 = { 0.5f + quadVertexData1[0] / 2f, 0.5f + quadVertexData1[1] / 2f, 0.5f + quadVertexData1[2] / 2f, 0.5f + quadVertexData1[3] / 2f, 0.5f + quadVertexData1[4] / 2f, 0.5f + quadVertexData1[5] / 2f, 0.5f + quadVertexData1[6] / 2f, 0.5f + quadVertexData1[7] / 2f, 0.5f + quadVertexData1[8] / 2f, 0.5f + quadVertexData1[9] / 2f, }; GL.Uniform1(Uniforms [(int)Uniform.Y], 0f); GL.VertexAttribPointer <float> ((int)Attrib.Vertex_Y, 2, VertexAttribPointerType.Float, false, 0, quadVertexData1); GL.EnableVertexAttribArray((int)Attrib.Vertex_Y); GL.VertexAttribPointer <float> ((int)Attrib.TexCoord_Y, 2, VertexAttribPointerType.Float, false, 0, quadTextureData1); GL.EnableVertexAttribArray((int)Attrib.TexCoord_Y); GL.DrawArrays(BeginMode.TriangleStrip, 0, 5); float[] quadVertexData2 = { (float)diagonalEnd2.X, (float)diagonalEnd2.Y, (float)diagonalEnd1.X, (float)diagonalEnd1.Y, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, }; quadVertexCoordinates(ref quadVertexData2, BackgroundTrack, tween); float[] quadTextureData2 = { 0.5f + quadVertexData2[0] / 2f, 0.5f + quadVertexData2[1] / 2f, 0.5f + quadVertexData2[2] / 2f, 0.5f + quadVertexData2[3] / 2f, 0.5f + quadVertexData2[4] / 2f, 0.5f + quadVertexData2[5] / 2f, 0.5f + quadVertexData2[6] / 2f, 0.5f + quadVertexData2[7] / 2f, 0.5f + quadVertexData2[8] / 2f, 0.5f + quadVertexData2[9] / 2f, }; GL.Uniform1(Uniforms [(int)Uniform.Y], 1); GL.VertexAttribPointer <float> ((int)Attrib.Vertex_Y, 2, VertexAttribPointerType.Float, false, 0, quadVertexData2); GL.EnableVertexAttribArray((int)Attrib.Vertex_Y); GL.VertexAttribPointer <float> ((int)Attrib.TexCoord_Y, 2, VertexAttribPointerType.Float, false, 0, quadTextureData2); GL.EnableVertexAttribArray((int)Attrib.TexCoord_Y); // Draw the background frame GL.DrawArrays(BeginMode.TriangleStrip, 0, 5); // Perform similar operations as above for the UV plane GL.UseProgram(ProgramUV); GL.UniformMatrix4(Uniforms [(int)Uniform.Render_Transform_UV], 1, false, preferredRenderTransform); // UV planes of foreground and background frame are used to render the UV plane of the destination frame GL.ActiveTexture(TextureUnit.Texture2); GL.BindTexture(foregroundChromaTexture.Target, foregroundChromaTexture.Name); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.ClampToEdge); GL.ActiveTexture(TextureUnit.Texture3); GL.BindTexture(backgroundChromaTexture.Target, backgroundChromaTexture.Name); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.ClampToEdge); GL.Viewport(0, 0, (int)destinationPixelBuffer.GetWidthOfPlane(1), (int)destinationPixelBuffer.GetHeightOfPlane(1)); // Attach the destination texture as a color attachment to the off screen frame buffer GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferSlot.ColorAttachment0, destChromaTexture.Target, destChromaTexture.Name, 0); if (GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != FramebufferErrorCode.FramebufferComplete) { Console.WriteLine("Failed to make complete framebuffer object: " + GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer).ToString()); foregroundLumaTexture.Dispose(); foregroundChromaTexture.Dispose(); backgroundLumaTexture.Dispose(); backgroundChromaTexture.Dispose(); destLumaTexture.Dispose(); destChromaTexture.Dispose(); // Periodic texture cache flush every frame VideoTextureCache.Flush(CoreVideo.CVOptionFlags.None); EAGLContext.SetCurrentContext(null); } GL.ClearColor(0f, 0f, 0f, 1f); GL.Clear(ClearBufferMask.ColorBufferBit); GL.Uniform1(Uniforms [(int)Uniform.UV], 2); GL.VertexAttribPointer <float> ((int)Attrib.Vertex_UV, 2, VertexAttribPointerType.Float, false, 0, quadVertexData1); GL.EnableVertexAttribArray((int)Attrib.Vertex_UV); GL.VertexAttribPointer <float> ((int)Attrib.TexCoord_UV, 2, VertexAttribPointerType.Float, false, 0, quadTextureData1); GL.EnableVertexAttribArray((int)Attrib.TexCoord_UV); GL.DrawArrays(BeginMode.TriangleStrip, 0, 5); GL.Uniform1(Uniforms [(int)Uniform.UV], 3); GL.VertexAttribPointer <float> ((int)Attrib.Vertex_UV, 2, VertexAttribPointerType.Float, false, 0, quadVertexData2); GL.EnableVertexAttribArray((int)Attrib.Vertex_UV); GL.VertexAttribPointer <float> ((int)Attrib.TexCoord_UV, 2, VertexAttribPointerType.Float, false, 0, quadTextureData2); GL.EnableVertexAttribArray((int)Attrib.TexCoord_UV); GL.DrawArrays(BeginMode.TriangleStrip, 0, 5); GL.Flush(); foregroundLumaTexture.Dispose(); foregroundChromaTexture.Dispose(); backgroundLumaTexture.Dispose(); backgroundChromaTexture.Dispose(); destLumaTexture.Dispose(); destChromaTexture.Dispose(); // Periodic texture cache flush every frame VideoTextureCache.Flush(CoreVideo.CVOptionFlags.None); EAGLContext.SetCurrentContext(null); }
public override void RenderPixelBuffer(MonoTouch.CoreVideo.CVPixelBuffer destinationPixelBuffer, MonoTouch.CoreVideo.CVPixelBuffer foregroundPixelBuffer, MonoTouch.CoreVideo.CVPixelBuffer backgroundPixelBuffer, float tween) { EAGLContext.SetCurrentContext(CurrentContext); if (foregroundPixelBuffer != null || backgroundPixelBuffer != null) { CVOpenGLESTexture foregroundLumaTexture = LumaTextureForPixelBuffer(foregroundPixelBuffer); CVOpenGLESTexture foregroundChromaTexture = ChromaTextureForPixelBuffer(foregroundPixelBuffer); CVOpenGLESTexture backgroundLumaTexture = LumaTextureForPixelBuffer(backgroundPixelBuffer); CVOpenGLESTexture backgroundChromaTexture = ChromaTextureForPixelBuffer(backgroundPixelBuffer); CVOpenGLESTexture destLumaTexture = LumaTextureForPixelBuffer(destinationPixelBuffer); CVOpenGLESTexture destChromaTexture = ChromaTextureForPixelBuffer(destinationPixelBuffer); GL.UseProgram(ProgramY); // Set the render transform float[] preferredRenderTransform = { RenderTransform.xx, RenderTransform.xy, RenderTransform.x0, 0.0f, RenderTransform.yx, RenderTransform.yy, RenderTransform.y0, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, }; GL.UniformMatrix4(Uniforms [(int)Uniform.Render_Transform_Y], 1, false, preferredRenderTransform); GL.BindFramebuffer(FramebufferTarget.Framebuffer, OffscreenBufferHandle); GL.Viewport(0, 0, destinationPixelBuffer.Width, destinationPixelBuffer.Height); GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(foregroundLumaTexture.Target, foregroundLumaTexture.Name); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.ClampToEdge); GL.ActiveTexture(TextureUnit.Texture1); GL.BindTexture(backgroundLumaTexture.Target, backgroundLumaTexture.Name); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.ClampToEdge); // Attach the destination texture as a color attachment to the off screen frame buffer GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferSlot.ColorAttachment0, destLumaTexture.Target, destLumaTexture.Name, 0); if (GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != FramebufferErrorCode.FramebufferComplete) { Console.Error.WriteLine("Failed to make complete framebuffer object " + GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer)); foregroundLumaTexture.Dispose(); foregroundChromaTexture.Dispose(); backgroundLumaTexture.Dispose(); backgroundChromaTexture.Dispose(); destLumaTexture.Dispose(); destChromaTexture.Dispose(); VideoTextureCache.Flush(0); EAGLContext.SetCurrentContext(null); return; } GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f); GL.Clear(ClearBufferMask.ColorBufferBit); float[] quadVertexData1 = { -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, }; // texture data varies from 0 -> 1, whereas vertex data varies from -1 -> 1 float[] quadTextureData1 = { 0.5f + quadVertexData1 [0] / 2, 0.5f + quadVertexData1 [1] / 2, 0.5f + quadVertexData1 [2] / 2, 0.5f + quadVertexData1 [3] / 2, 0.5f + quadVertexData1 [4] / 2, 0.5f + quadVertexData1 [5] / 2, 0.5f + quadVertexData1 [6] / 2, 0.5f + quadVertexData1 [7] / 2, }; GL.Uniform1(Uniforms [(int)Uniform.Y], 0); GL.VertexAttribPointer((int)Attrib.Vertex_Y, 2, VertexAttribPointerType.Float, false, 0, quadVertexData1); GL.EnableVertexAttribArray((int)Attrib.Vertex_Y); GL.VertexAttribPointer((int)Attrib.TexCoord_Y, 2, VertexAttribPointerType.Float, false, 0, quadTextureData1); GL.EnableVertexAttribArray((int)Attrib.TexCoord_Y); // Blend function to draw the foreground frame GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.Zero); // Draw the foreground frame GL.DrawArrays(BeginMode.TriangleStrip, 0, 4); GL.Uniform1(Uniforms [(int)Uniform.Y], 1); GL.VertexAttribPointer((int)Attrib.Vertex_Y, 2, VertexAttribPointerType.Float, false, 0, quadVertexData1); GL.EnableVertexAttribArray((int)Attrib.Vertex_Y); GL.VertexAttribPointer((int)Attrib.TexCoord_Y, 2, VertexAttribPointerType.Float, false, 0, quadTextureData1); GL.EnableVertexAttribArray((int)Attrib.TexCoord_Y); // Blend function to draw the background frame GL.BlendColor(0, 0, 0, tween); GL.BlendFunc(BlendingFactorSrc.ConstantAlpha, BlendingFactorDest.OneMinusConstantAlpha); // Draw the background frame GL.DrawArrays(BeginMode.TriangleStrip, 0, 4); // Perform similar operations as above for the UV plane GL.UseProgram(ProgramUV); GL.UniformMatrix4(Uniforms [(int)Uniform.Render_Transform_UV], 1, false, preferredRenderTransform); GL.ActiveTexture(TextureUnit.Texture2); GL.BindTexture(foregroundChromaTexture.Target, foregroundChromaTexture.Name); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.ClampToEdge); GL.ActiveTexture(TextureUnit.Texture3); GL.BindTexture(backgroundChromaTexture.Target, backgroundChromaTexture.Name); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.ClampToEdge); GL.Viewport(0, 0, destinationPixelBuffer.Width, destinationPixelBuffer.Height); // Attach the destination texture as a color attachment to the off screen frame buffer GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferSlot.ColorAttachment0, destChromaTexture.Target, destChromaTexture.Name, 0); if (GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != FramebufferErrorCode.FramebufferComplete) { Console.Error.WriteLine("Failed to make complete framebuffer object " + GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer)); foregroundLumaTexture.Dispose(); foregroundChromaTexture.Dispose(); backgroundLumaTexture.Dispose(); backgroundChromaTexture.Dispose(); destLumaTexture.Dispose(); destChromaTexture.Dispose(); this.VideoTextureCache.Flush(0); EAGLContext.SetCurrentContext(null); return; } GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f); GL.Clear(ClearBufferMask.ColorBufferBit); GL.Uniform1(Uniforms [(int)Uniform.UV], 2); GL.VertexAttribPointer((int)Attrib.Vertex_UV, 2, VertexAttribPointerType.Float, false, 0, quadVertexData1); GL.EnableVertexAttribArray((int)Attrib.Vertex_UV); GL.VertexAttribPointer((int)Attrib.TexCoord_UV, 2, VertexAttribPointerType.Float, false, 0, quadTextureData1); GL.EnableVertexAttribArray((int)Attrib.TexCoord_UV); // Blend function to draw the foreground frame GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.Zero); // Draw the foreground frame GL.DrawArrays(BeginMode.TriangleStrip, 0, 4); GL.Uniform1(Uniforms [(int)Uniform.UV], 3); GL.VertexAttribPointer((int)Attrib.Vertex_UV, 2, VertexAttribPointerType.Float, false, 0, quadVertexData1); GL.EnableVertexAttribArray((int)Attrib.Vertex_UV); GL.VertexAttribPointer((int)Attrib.TexCoord_UV, 2, VertexAttribPointerType.Float, false, 0, quadTextureData1); GL.EnableVertexAttribArray((int)Attrib.TexCoord_UV); // Blend function to draw the background frame GL.BlendColor(0, 0, 0, tween); GL.BlendFunc(BlendingFactorSrc.ConstantAlpha, BlendingFactorDest.OneMinusConstantAlpha); // Draw the background frame GL.DrawArrays(BeginMode.TriangleStrip, 0, 4); GL.Flush(); foregroundLumaTexture.Dispose(); foregroundChromaTexture.Dispose(); backgroundLumaTexture.Dispose(); backgroundChromaTexture.Dispose(); destLumaTexture.Dispose(); destChromaTexture.Dispose(); this.VideoTextureCache.Flush(0); EAGLContext.SetCurrentContext(null); } }