private void GL_pushState() { // Begin the effect, flagging to restore previous state on end FNA3D.FNA3D_BeginPassRestore( currentDevice.GLDevice, shaderProgram.glEffect, stateChangesPtr ); // Prep our samplers for (int i = 0; i < 3; i += 1) { oldTextures[i] = currentDevice.Textures[i]; oldSamplers[i] = currentDevice.SamplerStates[i]; currentDevice.Textures[i] = yuvTextures[i]; currentDevice.SamplerStates[i] = SamplerState.LinearClamp; } // Prep buffers oldBuffers = currentDevice.GetVertexBuffers(); currentDevice.SetVertexBuffers(vertBuffer); // Prep target bindings oldTargets = currentDevice.GetRenderTargets(); unsafe { fixed(FNA3D.FNA3D_RenderTargetBinding *rt = &nativeVideoTexture[0]) { GraphicsDevice.PrepareRenderTargetBindings( rt, videoTexture ); FNA3D.FNA3D_SetRenderTargets( currentDevice.GLDevice, rt, videoTexture.Length, IntPtr.Zero, DepthFormat.None, 0 ); } } // Prep render state prevBlend = currentDevice.BlendState; prevDepthStencil = currentDevice.DepthStencilState; prevRasterizer = currentDevice.RasterizerState; currentDevice.BlendState = BlendState.Opaque; currentDevice.DepthStencilState = DepthStencilState.None; currentDevice.RasterizerState = RasterizerState.CullNone; // Prep viewport prevViewport = currentDevice.Viewport; FNA3D.FNA3D_SetViewport( currentDevice.GLDevice, ref viewport.viewport ); }
private void GL_popState() { // End the effect, restoring the previous shader state FNA3D.FNA3D_EndPassRestore( currentDevice.GLDevice, shaderProgram.glEffect ); // Restore GL state currentDevice.BlendState = prevBlend; currentDevice.DepthStencilState = prevDepthStencil; currentDevice.RasterizerState = prevRasterizer; prevBlend = null; prevDepthStencil = null; prevRasterizer = null; /* Restore targets using GLDevice directly. * This prevents accidental clearing of previously bound targets. */ if (oldTargets == null || oldTargets.Length == 0) { FNA3D.FNA3D_SetRenderTargets( currentDevice.GLDevice, IntPtr.Zero, 0, IntPtr.Zero, DepthFormat.None, 0 ); } else { IRenderTarget oldTarget = oldTargets[0].RenderTarget as IRenderTarget; unsafe { fixed(FNA3D.FNA3D_RenderTargetBinding *rt = &nativeOldTargets[0]) { GraphicsDevice.PrepareRenderTargetBindings( rt, oldTargets ); FNA3D.FNA3D_SetRenderTargets( currentDevice.GLDevice, rt, oldTargets.Length, oldTarget.DepthStencilBuffer, oldTarget.DepthStencilFormat, (byte)(oldTarget.RenderTargetUsage != RenderTargetUsage.DiscardContents ? 1 : 0) /* lol c# */ ); } } } oldTargets = null; // Set viewport AFTER setting targets! FNA3D.FNA3D_SetViewport( currentDevice.GLDevice, ref prevViewport.viewport ); // Restore buffers currentDevice.SetVertexBuffers(oldBuffers); oldBuffers = null; // Restore samplers for (int i = 0; i < 3; i += 1) { /* The application may have set a texture ages * ago, only to not unset after disposing. We * have to avoid an ObjectDisposedException! */ if (oldTextures[i] == null || !oldTextures[i].IsDisposed) { currentDevice.Textures[i] = oldTextures[i]; } currentDevice.SamplerStates[i] = oldSamplers[i]; oldTextures[i] = null; oldSamplers[i] = null; } }