From 3cf53c4d9a11f78a9f9403ddefe41cdc8c7fd35f Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 11 May 2020 14:01:17 +0200 Subject: [PATCH] OpenGL: Implement RenderPipeline --- .../OpenGLRenderer/OpenGLRenderPipeline.hpp | 54 +--- .../OpenGLRenderer/OpenGLRenderPipeline.inl | 4 + .../Nazara/OpenGLRenderer/Wrapper/Context.hpp | 2 + .../OpenGLRenderer/OpenGLRenderPipeline.cpp | 264 +----------------- src/Nazara/OpenGLRenderer/Wrapper/Context.cpp | 151 ++++++++++ 5 files changed, 177 insertions(+), 298 deletions(-) diff --git a/include/Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp b/include/Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp index 4cddfc828..ddc6526af 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp @@ -11,9 +11,7 @@ #include #include #include -#include -#include -#include +#include #include namespace Nz @@ -21,58 +19,16 @@ namespace Nz class NAZARA_OPENGLRENDERER_API OpenGLRenderPipeline : public RenderPipeline { public: - struct CreateInfo; - - OpenGLRenderPipeline(Vk::Device& device, RenderPipelineInfo pipelineInfo); + OpenGLRenderPipeline(OpenGLDevice& device, RenderPipelineInfo pipelineInfo); ~OpenGLRenderPipeline() = default; - VkPipeline Get(const Vk::RenderPass& renderPass) const; + void Apply(const GL::Context& context) const; - static std::vector BuildColorBlendAttachmentStateList(const RenderPipelineInfo& pipelineInfo); - static VkPipelineColorBlendStateCreateInfo BuildColorBlendInfo(const RenderPipelineInfo& pipelineInfo, const std::vector& attachmentState); - static VkPipelineDepthStencilStateCreateInfo BuildDepthStencilInfo(const RenderPipelineInfo& pipelineInfo); - static VkPipelineDynamicStateCreateInfo BuildDynamicStateInfo(const RenderPipelineInfo& pipelineInfo, const std::vector& dynamicStates); - static std::vector BuildDynamicStateList(const RenderPipelineInfo& pipelineInfo); - static VkPipelineInputAssemblyStateCreateInfo BuildInputAssemblyInfo(const RenderPipelineInfo& pipelineInfo); - static VkPipelineMultisampleStateCreateInfo BuildMultisampleInfo(const RenderPipelineInfo& pipelineInfo); - static VkPipelineRasterizationStateCreateInfo BuildRasterizationInfo(const RenderPipelineInfo& pipelineInfo); - static VkPipelineViewportStateCreateInfo BuildViewportInfo(const RenderPipelineInfo& pipelineInfo); - static VkStencilOpState BuildStencilOp(const RenderPipelineInfo& pipelineInfo, bool front); - static std::vector BuildShaderStageInfo(const RenderPipelineInfo& pipelineInfo); - static std::vector BuildVertexAttributeDescription(const RenderPipelineInfo& pipelineInfo); - static std::vector BuildVertexBindingDescription(const RenderPipelineInfo& pipelineInfo); - static VkPipelineVertexInputStateCreateInfo BuildVertexInputInfo(const RenderPipelineInfo& pipelineInfo, const std::vector& vertexAttributes, const std::vector& bindingDescription); - - static CreateInfo BuildCreateInfo(const RenderPipelineInfo& pipelineInfo); - - struct CreateInfo - { - struct StateData - { - VkPipelineColorBlendStateCreateInfo colorBlendState; - VkPipelineDepthStencilStateCreateInfo depthStencilState; - VkPipelineDynamicStateCreateInfo dynamicState; - VkPipelineMultisampleStateCreateInfo multiSampleState; - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState; - VkPipelineRasterizationStateCreateInfo rasterizationState; - VkPipelineVertexInputStateCreateInfo vertexInputState; - VkPipelineViewportStateCreateInfo viewportState; - }; - - std::vector colorBlendAttachmentState; - std::vector dynamicStates; - std::vector shaderStages; - std::vector vertexAttributesDescription; - std::vector vertexBindingDescription; - std::unique_ptr stateData; - VkGraphicsPipelineCreateInfo pipelineInfo; - }; + inline const RenderPipelineInfo& GetPipelineInfo() const; private: - mutable std::unordered_map m_pipelines; - MovablePtr m_device; - CreateInfo m_pipelineCreateInfo; RenderPipelineInfo m_pipelineInfo; + GL::Program m_program; }; } diff --git a/include/Nazara/OpenGLRenderer/OpenGLRenderPipeline.inl b/include/Nazara/OpenGLRenderer/OpenGLRenderPipeline.inl index 034fea18c..0b4dc1a95 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLRenderPipeline.inl +++ b/include/Nazara/OpenGLRenderer/OpenGLRenderPipeline.inl @@ -7,6 +7,10 @@ namespace Nz { + inline const RenderPipelineInfo& OpenGLRenderPipeline::GetPipelineInfo() const + { + return m_pipelineInfo; + } } #include diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp b/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp index d18843c08..96378fa22 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp @@ -113,6 +113,8 @@ namespace Nz::GL virtual void SwapBuffers() = 0; + void UpdateStates(const RenderStates& renderStates) const; + #define NAZARA_OPENGLRENDERER_FUNC(name, sig) sig name = nullptr; NAZARA_OPENGLRENDERER_FOREACH_GLES_FUNC(NAZARA_OPENGLRENDERER_FUNC, NAZARA_OPENGLRENDERER_FUNC) #undef NAZARA_OPENGLRENDERER_FUNC diff --git a/src/Nazara/OpenGLRenderer/OpenGLRenderPipeline.cpp b/src/Nazara/OpenGLRenderer/OpenGLRenderPipeline.cpp index a57b7b1ed..d3378c941 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLRenderPipeline.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLRenderPipeline.cpp @@ -2,273 +2,39 @@ // This file is part of the "Nazara Engine - OpenGL Renderer" // For conditions of distribution and use, see copyright notice in Config.hpp -#if 0 - #include #include #include #include #include #include +#include #include namespace Nz { - OpenGLRenderPipeline::OpenGLRenderPipeline(Vk::Device& device, RenderPipelineInfo pipelineInfo) : - m_device(&device), + OpenGLRenderPipeline::OpenGLRenderPipeline(OpenGLDevice& device, RenderPipelineInfo pipelineInfo) : m_pipelineInfo(std::move(pipelineInfo)) { - m_pipelineCreateInfo = BuildCreateInfo(m_pipelineInfo); - } + if (!m_program.Create(device)) + throw std::runtime_error("failed to create program"); - VkPipeline OpenGLRenderPipeline::Get(const Vk::RenderPass& renderPass) const - { - if (auto it = m_pipelines.find(renderPass); it != m_pipelines.end()) - return it->second; - - // Copy create info to make Get re-entrant - VkGraphicsPipelineCreateInfo pipelineCreateInfo = m_pipelineCreateInfo.pipelineInfo; - pipelineCreateInfo.renderPass = renderPass; - - Vk::Pipeline newPipeline; - if (!newPipeline.CreateGraphics(*m_device, pipelineCreateInfo)) - return VK_NULL_HANDLE; - - auto it = m_pipelines.emplace(renderPass, std::move(newPipeline)).first; - return it->second; - } - - std::vector OpenGLRenderPipeline::BuildColorBlendAttachmentStateList(const RenderPipelineInfo& pipelineInfo) - { - std::vector colorBlendStates; - - VkPipelineColorBlendAttachmentState& colorBlendState = colorBlendStates.emplace_back(); - colorBlendState.blendEnable = pipelineInfo.blending; - colorBlendState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; //< TODO - - if (pipelineInfo.blending) + for (const auto& shaderStagePtr : m_pipelineInfo.shaderStages) { - //TODO - /*switch (pipelineInfo.dstBlend) - { - blendState.dstAlphaBlendFactor - }*/ - } - else - { - colorBlendState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; - colorBlendState.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; - colorBlendState.colorBlendOp = VK_BLEND_OP_ADD; - colorBlendState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; - colorBlendState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; - colorBlendState.alphaBlendOp = VK_BLEND_OP_ADD; + OpenGLShaderStage& shaderStage = static_cast(*shaderStagePtr); + m_program.AttachShader(shaderStage.GetShader().GetObjectId()); } - return colorBlendStates; + m_program.Link(); + + std::string errLog; + if (!m_program.GetLinkStatus(&errLog)) + throw std::runtime_error("failed to link program: " + errLog); } - VkPipelineColorBlendStateCreateInfo OpenGLRenderPipeline::BuildColorBlendInfo(const RenderPipelineInfo& pipelineInfo, const std::vector& attachmentState) + void OpenGLRenderPipeline::Apply(const GL::Context& context) const { - VkPipelineColorBlendStateCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - createInfo.attachmentCount = std::uint32_t(attachmentState.size()); - createInfo.pAttachments = attachmentState.data(); - - return createInfo; - } - - VkPipelineDepthStencilStateCreateInfo OpenGLRenderPipeline::BuildDepthStencilInfo(const RenderPipelineInfo& pipelineInfo) - { - VkPipelineDepthStencilStateCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - createInfo.depthTestEnable = pipelineInfo.depthBuffer; - createInfo.depthWriteEnable = pipelineInfo.depthWrite; - createInfo.depthCompareOp = ToOpenGL(pipelineInfo.depthCompare); - createInfo.stencilTestEnable = pipelineInfo.stencilTest; - createInfo.front = BuildStencilOp(pipelineInfo, true); - createInfo.back = BuildStencilOp(pipelineInfo, false); - - return createInfo; - } - - VkPipelineDynamicStateCreateInfo OpenGLRenderPipeline::BuildDynamicStateInfo(const RenderPipelineInfo& pipelineInfo, const std::vector& dynamicStates) - { - VkPipelineDynamicStateCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - createInfo.dynamicStateCount = std::uint32_t(dynamicStates.size()); - createInfo.pDynamicStates = dynamicStates.data(); - - return createInfo; - } - - std::vector OpenGLRenderPipeline::BuildDynamicStateList(const RenderPipelineInfo& pipelineInfo) - { - return { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - } - - VkPipelineInputAssemblyStateCreateInfo OpenGLRenderPipeline::BuildInputAssemblyInfo(const RenderPipelineInfo& pipelineInfo) - { - VkPipelineInputAssemblyStateCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - createInfo.topology = ToOpenGL(pipelineInfo.primitiveMode); - - return createInfo; - } - - VkPipelineMultisampleStateCreateInfo OpenGLRenderPipeline::BuildMultisampleInfo(const RenderPipelineInfo& pipelineInfo) - { - VkPipelineMultisampleStateCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - createInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - createInfo.minSampleShading = 1.0f; //< TODO: Remove - - return createInfo; - } - - VkPipelineRasterizationStateCreateInfo OpenGLRenderPipeline::BuildRasterizationInfo(const RenderPipelineInfo& pipelineInfo) - { - VkPipelineRasterizationStateCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - createInfo.polygonMode = ToOpenGL(pipelineInfo.faceFilling); - createInfo.cullMode = ToOpenGL(pipelineInfo.cullingSide); - createInfo.frontFace = VK_FRONT_FACE_CLOCKWISE; //< TODO - createInfo.lineWidth = pipelineInfo.lineWidth; - - return createInfo; - } - - VkPipelineViewportStateCreateInfo OpenGLRenderPipeline::BuildViewportInfo(const RenderPipelineInfo& pipelineInfo) - { - VkPipelineViewportStateCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - createInfo.scissorCount = createInfo.viewportCount = 1; //< TODO - - return createInfo; - } - - VkStencilOpState OpenGLRenderPipeline::BuildStencilOp(const RenderPipelineInfo& pipelineInfo, bool front) - { - const auto& pipelineStencil = (front) ? pipelineInfo.stencilFront : pipelineInfo.stencilBack; - - VkStencilOpState stencilStates; - stencilStates.compareMask = pipelineStencil.compareMask; - stencilStates.compareOp = ToOpenGL(pipelineStencil.compare); - stencilStates.depthFailOp = ToOpenGL(pipelineStencil.depthFail); - stencilStates.failOp = ToOpenGL(pipelineStencil.fail); - stencilStates.passOp = ToOpenGL(pipelineStencil.pass); - stencilStates.reference = pipelineStencil.reference; - stencilStates.writeMask = pipelineStencil.writeMask; - - return stencilStates; - } - - std::vector OpenGLRenderPipeline::BuildShaderStageInfo(const RenderPipelineInfo& pipelineInfo) - { - std::vector shaderStageCreateInfos; - - for (auto&& stagePtr : pipelineInfo.shaderStages) - { - Nz::OpenGLShaderStage& vulkanStage = *static_cast(stagePtr.get()); - - VkPipelineShaderStageCreateInfo& createInfo = shaderStageCreateInfos.emplace_back(); - createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - createInfo.module = vulkanStage.GetHandle(); - createInfo.pName = "main"; - createInfo.stage = ToOpenGL(vulkanStage.GetStageType()); - } - - return shaderStageCreateInfos; - } - - std::vector OpenGLRenderPipeline::BuildVertexAttributeDescription(const RenderPipelineInfo& pipelineInfo) - { - std::vector vertexAttributes; - - std::uint32_t locationIndex = 0; - - for (const auto& bufferData : pipelineInfo.vertexBuffers) - { - std::uint32_t binding = std::uint32_t(bufferData.binding); - - for (const auto& componentInfo : *bufferData.declaration) - { - auto& bufferAttribute = vertexAttributes.emplace_back(); - bufferAttribute.binding = binding; - bufferAttribute.location = locationIndex++; - bufferAttribute.offset = std::uint32_t(componentInfo.offset); - bufferAttribute.format = ToOpenGL(componentInfo.type); - } - } - - return vertexAttributes; - } - - std::vector OpenGLRenderPipeline::BuildVertexBindingDescription(const RenderPipelineInfo& pipelineInfo) - { - std::vector vertexBindings; - - for (const auto& bufferData : pipelineInfo.vertexBuffers) - { - auto& bufferBinding = vertexBindings.emplace_back(); - bufferBinding.binding = std::uint32_t(bufferData.binding); - bufferBinding.stride = std::uint32_t(bufferData.declaration->GetStride()); - bufferBinding.inputRate = ToOpenGL(bufferData.declaration->GetInputRate()); - } - - return vertexBindings; - } - - VkPipelineVertexInputStateCreateInfo OpenGLRenderPipeline::BuildVertexInputInfo(const RenderPipelineInfo& pipelineInfo, const std::vector& vertexAttributes, const std::vector& bindingDescriptions) - { - VkPipelineVertexInputStateCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - - createInfo.vertexAttributeDescriptionCount = std::uint32_t(vertexAttributes.size()); - createInfo.pVertexAttributeDescriptions = vertexAttributes.data(); - - createInfo.vertexBindingDescriptionCount = std::uint32_t(bindingDescriptions.size()); - createInfo.pVertexBindingDescriptions = bindingDescriptions.data(); - - return createInfo; - } - - auto OpenGLRenderPipeline::BuildCreateInfo(const RenderPipelineInfo& pipelineInfo) -> CreateInfo - { - CreateInfo createInfo = {}; - createInfo.stateData = std::make_unique(); - - createInfo.colorBlendAttachmentState = BuildColorBlendAttachmentStateList(pipelineInfo); - createInfo.dynamicStates = BuildDynamicStateList(pipelineInfo); - createInfo.shaderStages = BuildShaderStageInfo(pipelineInfo); - createInfo.vertexAttributesDescription = BuildVertexAttributeDescription(pipelineInfo); - createInfo.vertexBindingDescription = BuildVertexBindingDescription(pipelineInfo); - - createInfo.stateData->colorBlendState = BuildColorBlendInfo(pipelineInfo, createInfo.colorBlendAttachmentState); - createInfo.stateData->depthStencilState = BuildDepthStencilInfo(pipelineInfo); - createInfo.stateData->dynamicState = BuildDynamicStateInfo(pipelineInfo, createInfo.dynamicStates); - createInfo.stateData->inputAssemblyState = BuildInputAssemblyInfo(pipelineInfo); - createInfo.stateData->multiSampleState = BuildMultisampleInfo(pipelineInfo); - createInfo.stateData->rasterizationState = BuildRasterizationInfo(pipelineInfo); - createInfo.stateData->viewportState = BuildViewportInfo(pipelineInfo); - createInfo.stateData->vertexInputState = BuildVertexInputInfo(pipelineInfo, createInfo.vertexAttributesDescription, createInfo.vertexBindingDescription); - - createInfo.pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - createInfo.pipelineInfo.stageCount = std::uint32_t(createInfo.shaderStages.size()); - createInfo.pipelineInfo.pStages = createInfo.shaderStages.data(); - createInfo.pipelineInfo.pColorBlendState = &createInfo.stateData->colorBlendState; - createInfo.pipelineInfo.pDepthStencilState = &createInfo.stateData->depthStencilState; - createInfo.pipelineInfo.pDynamicState = &createInfo.stateData->dynamicState; - createInfo.pipelineInfo.pInputAssemblyState = &createInfo.stateData->inputAssemblyState; - createInfo.pipelineInfo.pMultisampleState = &createInfo.stateData->multiSampleState; - createInfo.pipelineInfo.pRasterizationState = &createInfo.stateData->rasterizationState; - createInfo.pipelineInfo.pVertexInputState = &createInfo.stateData->vertexInputState; - createInfo.pipelineInfo.pViewportState = &createInfo.stateData->viewportState; - - OpenGLRenderPipelineLayout& pipelineLayout = *static_cast(pipelineInfo.pipelineLayout.get()); - createInfo.pipelineInfo.layout = pipelineLayout.GetPipelineLayout(); - - return createInfo; + context.UpdateStates(m_pipelineInfo); + context.BindProgram(m_program.GetObjectId()); //< Bind program after states } } - -#endif diff --git a/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp b/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp index e1240d365..3d7417f6d 100644 --- a/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp +++ b/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp @@ -197,6 +197,157 @@ namespace Nz::GL return true; } + void Context::UpdateStates(const RenderStates& renderStates) const + { + if (!SetCurrentContext(this)) + throw std::runtime_error("failed to activate context"); + + if (renderStates.blending) + { + if (m_state.renderStates.dstBlend != renderStates.dstBlend || + m_state.renderStates.srcBlend != renderStates.srcBlend) + { + glBlendFunc(ToOpenGL(renderStates.srcBlend), ToOpenGL(renderStates.dstBlend)); + m_state.renderStates.dstBlend = renderStates.dstBlend; + m_state.renderStates.srcBlend = renderStates.srcBlend; + } + } + + if (renderStates.depthBuffer) + { + if (m_state.renderStates.depthCompare != renderStates.depthCompare) + { + glDepthFunc(ToOpenGL(m_state.renderStates.depthCompare)); + m_state.renderStates.depthCompare = renderStates.depthCompare; + } + + if (m_state.renderStates.depthWrite != renderStates.depthWrite) + { + glDepthMask((renderStates.depthWrite) ? GL_TRUE : GL_FALSE); + m_state.renderStates.depthWrite = renderStates.depthWrite; + } + } + + if (renderStates.faceCulling) + { + if (m_state.renderStates.cullingSide != renderStates.cullingSide) + { + glCullFace(ToOpenGL(m_state.renderStates.cullingSide)); + m_state.renderStates.cullingSide = renderStates.cullingSide; + } + } + + /* + TODO: Use glPolyonMode if available (OpenGL) + if (m_state.renderStates.faceFilling != renderStates.faceFilling) + { + glPolygonMode(GL_FRONT_AND_BACK, FaceFilling[states.faceFilling]); + m_state.renderStates.faceFilling = renderStates.faceFilling; + }*/ + + if (renderStates.stencilTest) + { + auto ApplyStencilStates = [&](bool front) + { + auto& currentStencilData = (front) ? m_state.renderStates.stencilFront : m_state.renderStates.stencilBack; + auto& newStencilData = (front) ? renderStates.stencilFront : renderStates.stencilBack; + + if (currentStencilData.compare != newStencilData.compare || + currentStencilData.reference != newStencilData.reference || + currentStencilData.writeMask != newStencilData.writeMask) + { + glStencilFuncSeparate((front) ? GL_FRONT : GL_BACK, ToOpenGL(newStencilData.compare), newStencilData.reference, newStencilData.writeMask); + currentStencilData.compare = newStencilData.compare; + currentStencilData.reference = newStencilData.reference; + currentStencilData.writeMask = newStencilData.writeMask; + } + + if (currentStencilData.depthFail != newStencilData.depthFail || + currentStencilData.fail != newStencilData.fail || + currentStencilData.pass != newStencilData.pass) + { + glStencilOpSeparate((front) ? GL_FRONT : GL_BACK, ToOpenGL(newStencilData.fail), ToOpenGL(newStencilData.depthFail), ToOpenGL(newStencilData.pass)); + currentStencilData.depthFail = newStencilData.depthFail; + currentStencilData.fail = newStencilData.fail; + currentStencilData.pass = newStencilData.pass; + } + }; + + ApplyStencilStates(true); + ApplyStencilStates(false); + } + + if (!NumberEquals(m_state.renderStates.lineWidth, renderStates.lineWidth, 0.001f)) + { + glLineWidth(renderStates.lineWidth); + m_state.renderStates.lineWidth = renderStates.lineWidth; + } + + /*if (!NumberEquals(m_state.renderStates.pointSize, renderStates.pointSize, 0.001f)) + { + glPointSize(renderStates.pointSize); + m_state.renderStates.pointSize = renderStates.pointSize; + }*/ + + if (m_state.renderStates.blending != renderStates.blending) + { + if (renderStates.blending) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + + m_state.renderStates.blending = renderStates.blending; + } + + if (m_state.renderStates.colorWrite != renderStates.colorWrite) + { + GLboolean param = (renderStates.colorWrite) ? GL_TRUE : GL_FALSE; + glColorMask(param, param, param, param); + + m_state.renderStates.colorWrite = renderStates.colorWrite; + } + + if (m_state.renderStates.depthBuffer != renderStates.depthBuffer) + { + if (renderStates.depthBuffer) + glEnable(GL_DEPTH_TEST); + else + glDisable(GL_DEPTH_TEST); + + m_state.renderStates.depthBuffer = renderStates.depthBuffer; + } + + if (m_state.renderStates.faceCulling != renderStates.faceCulling) + { + if (renderStates.faceCulling) + glEnable(GL_CULL_FACE); + else + glDisable(GL_CULL_FACE); + + m_state.renderStates.faceCulling = renderStates.faceCulling; + } + + if (m_state.renderStates.scissorTest != renderStates.scissorTest) + { + if (renderStates.scissorTest) + glEnable(GL_SCISSOR_TEST); + else + glDisable(GL_SCISSOR_TEST); + + m_state.renderStates.scissorTest = renderStates.scissorTest; + } + + if (m_state.renderStates.stencilTest != renderStates.stencilTest) + { + if (renderStates.stencilTest) + glEnable(GL_STENCIL_TEST); + else + glDisable(GL_STENCIL_TEST); + + m_state.renderStates.stencilTest = renderStates.stencilTest; + } + } + const Context* Context::GetCurrentContext() { return s_currentContext;