public void Bind(GalPipelineState New) { BindConstBuffers(New); BindVertexLayout(New); if (New.FramebufferSrgb != _old.FramebufferSrgb) { Enable(EnableCap.FramebufferSrgb, New.FramebufferSrgb); _renderTarget.FramebufferSrgb = New.FramebufferSrgb; } if (New.FlipX != _old.FlipX || New.FlipY != _old.FlipY || New.Instance != _old.Instance) { _shader.SetExtraData(New.FlipX, New.FlipY, New.Instance); } if (New.FrontFace != _old.FrontFace) { GL.FrontFace(OglEnumConverter.GetFrontFace(New.FrontFace)); } if (New.CullFaceEnabled != _old.CullFaceEnabled) { Enable(EnableCap.CullFace, New.CullFaceEnabled); } if (New.CullFaceEnabled) { if (New.CullFace != _old.CullFace) { GL.CullFace(OglEnumConverter.GetCullFace(New.CullFace)); } } if (New.DepthTestEnabled != _old.DepthTestEnabled) { Enable(EnableCap.DepthTest, New.DepthTestEnabled); } if (New.DepthWriteEnabled != _old.DepthWriteEnabled) { GL.DepthMask(New.DepthWriteEnabled); } if (New.DepthTestEnabled) { if (New.DepthFunc != _old.DepthFunc) { GL.DepthFunc(OglEnumConverter.GetDepthFunc(New.DepthFunc)); } } if (New.DepthRangeNear != _old.DepthRangeNear || New.DepthRangeFar != _old.DepthRangeFar) { GL.DepthRange(New.DepthRangeNear, New.DepthRangeFar); } if (New.StencilTestEnabled != _old.StencilTestEnabled) { Enable(EnableCap.StencilTest, New.StencilTestEnabled); } if (New.StencilTwoSideEnabled != _old.StencilTwoSideEnabled) { Enable((EnableCap)All.StencilTestTwoSideExt, New.StencilTwoSideEnabled); } if (New.StencilTestEnabled) { if (New.StencilBackFuncFunc != _old.StencilBackFuncFunc || New.StencilBackFuncRef != _old.StencilBackFuncRef || New.StencilBackFuncMask != _old.StencilBackFuncMask) { GL.StencilFuncSeparate( StencilFace.Back, OglEnumConverter.GetStencilFunc(New.StencilBackFuncFunc), New.StencilBackFuncRef, New.StencilBackFuncMask); } if (New.StencilBackOpFail != _old.StencilBackOpFail || New.StencilBackOpZFail != _old.StencilBackOpZFail || New.StencilBackOpZPass != _old.StencilBackOpZPass) { GL.StencilOpSeparate( StencilFace.Back, OglEnumConverter.GetStencilOp(New.StencilBackOpFail), OglEnumConverter.GetStencilOp(New.StencilBackOpZFail), OglEnumConverter.GetStencilOp(New.StencilBackOpZPass)); } if (New.StencilBackMask != _old.StencilBackMask) { GL.StencilMaskSeparate(StencilFace.Back, New.StencilBackMask); } if (New.StencilFrontFuncFunc != _old.StencilFrontFuncFunc || New.StencilFrontFuncRef != _old.StencilFrontFuncRef || New.StencilFrontFuncMask != _old.StencilFrontFuncMask) { GL.StencilFuncSeparate( StencilFace.Front, OglEnumConverter.GetStencilFunc(New.StencilFrontFuncFunc), New.StencilFrontFuncRef, New.StencilFrontFuncMask); } if (New.StencilFrontOpFail != _old.StencilFrontOpFail || New.StencilFrontOpZFail != _old.StencilFrontOpZFail || New.StencilFrontOpZPass != _old.StencilFrontOpZPass) { GL.StencilOpSeparate( StencilFace.Front, OglEnumConverter.GetStencilOp(New.StencilFrontOpFail), OglEnumConverter.GetStencilOp(New.StencilFrontOpZFail), OglEnumConverter.GetStencilOp(New.StencilFrontOpZPass)); } if (New.StencilFrontMask != _old.StencilFrontMask) { GL.StencilMaskSeparate(StencilFace.Front, New.StencilFrontMask); } } // Scissor Test // All scissor test are disabled before drawing final framebuffer to screen so we don't need to handle disabling // Skip if there are no scissor tests to enable if (New.ScissorTestCount != 0) { int scissorsApplied = 0; bool applyToAll = false; for (int index = 0; index < GalPipelineState.RenderTargetsCount; index++) { if (New.ScissorTestEnabled[index]) { // If viewport arrays are unavailable apply first scissor test to all or // there is only 1 scissor test and it's the first, the scissor test applies to all viewports if (!OglExtension.Required.ViewportArray || (index == 0 && New.ScissorTestCount == 1)) { GL.Enable(EnableCap.ScissorTest); applyToAll = true; } else { GL.Enable(IndexedEnableCap.ScissorTest, index); } if (New.ScissorTestEnabled[index] != _old.ScissorTestEnabled[index] || New.ScissorTestX[index] != _old.ScissorTestX[index] || New.ScissorTestY[index] != _old.ScissorTestY[index] || New.ScissorTestWidth[index] != _old.ScissorTestWidth[index] || New.ScissorTestHeight[index] != _old.ScissorTestHeight[index]) { if (applyToAll) { GL.Scissor(New.ScissorTestX[index], New.ScissorTestY[index], New.ScissorTestWidth[index], New.ScissorTestHeight[index]); } else { GL.ScissorIndexed(index, New.ScissorTestX[index], New.ScissorTestY[index], New.ScissorTestWidth[index], New.ScissorTestHeight[index]); } } // If all scissor tests have been applied, or viewport arrays are unavailable we can skip remaining iterations if (!OglExtension.Required.ViewportArray || ++scissorsApplied == New.ScissorTestCount) { break; } } } } if (New.BlendIndependent) { for (int index = 0; index < GalPipelineState.RenderTargetsCount; index++) { SetBlendState(index, New.Blends[index], _old.Blends[index]); } } else { if (New.BlendIndependent != _old.BlendIndependent) { SetAllBlendState(New.Blends[0]); } else { SetBlendState(New.Blends[0], _old.Blends[0]); } } if (New.ColorMaskCommon) { if (New.ColorMaskCommon != _old.ColorMaskCommon || !New.ColorMasks[0].Equals(_old.ColorMasks[0])) { GL.ColorMask( New.ColorMasks[0].Red, New.ColorMasks[0].Green, New.ColorMasks[0].Blue, New.ColorMasks[0].Alpha); } } else { for (int index = 0; index < GalPipelineState.RenderTargetsCount; index++) { if (!New.ColorMasks[index].Equals(_old.ColorMasks[index])) { GL.ColorMask( index, New.ColorMasks[index].Red, New.ColorMasks[index].Green, New.ColorMasks[index].Blue, New.ColorMasks[index].Alpha); } } } if (New.PrimitiveRestartEnabled != _old.PrimitiveRestartEnabled) { Enable(EnableCap.PrimitiveRestart, New.PrimitiveRestartEnabled); } if (New.PrimitiveRestartEnabled) { if (New.PrimitiveRestartIndex != _old.PrimitiveRestartIndex) { GL.PrimitiveRestartIndex(New.PrimitiveRestartIndex); } } _old = New; }