#include "XCEngine/RHI/OpenGL/OpenGLPipelineState.h" #include namespace XCEngine { namespace RHI { OpenGLPipelineState::OpenGLPipelineState() : m_program(0), m_programAttached(false) { } OpenGLPipelineState::~OpenGLPipelineState() { } void OpenGLPipelineState::SetInputLayout(const InputLayoutDesc& layout) { m_inputLayoutDesc = layout; } void OpenGLPipelineState::SetRasterizerState(const RasterizerDesc& state) { m_rasterizerDesc = state; } void OpenGLPipelineState::SetBlendState(const BlendDesc& state) { m_blendDesc = state; } void OpenGLPipelineState::SetDepthStencilState(const DepthStencilStateDesc& state) { m_depthStencilDesc = state; } void OpenGLPipelineState::SetTopology(uint32_t topologyType) { m_topologyType = topologyType; } void OpenGLPipelineState::SetRenderTargetFormats(uint32_t count, const uint32_t* formats, uint32_t depthFormat) { } void OpenGLPipelineState::SetSampleCount(uint32_t count) { } PipelineStateHash OpenGLPipelineState::GetHash() const { PipelineStateHash hash = {}; return hash; } void OpenGLPipelineState::Shutdown() { m_program = 0; m_programAttached = false; } void OpenGLPipelineState::Bind() { if (m_programAttached) { glUseProgram(m_program); } Apply(); } void OpenGLPipelineState::Unbind() { glUseProgram(0); } void OpenGLPipelineState::Apply() { ApplyDepthStencil(); ApplyBlend(); ApplyRasterizer(); } void OpenGLPipelineState::ApplyDepthStencil() { if (m_glDepthStencilState.depthTestEnable) { glEnable(GL_DEPTH_TEST); } else { glDisable(GL_DEPTH_TEST); } glDepthMask(m_glDepthStencilState.depthWriteEnable ? GL_TRUE : GL_FALSE); glDepthFunc(static_cast(m_glDepthStencilState.depthFunc)); if (m_glDepthStencilState.stencilEnable) { glEnable(GL_STENCIL_TEST); glStencilMask(m_glDepthStencilState.stencilWriteMask); glStencilFunc( static_cast(m_glDepthStencilState.stencilFunc), m_glDepthStencilState.stencilRef, m_glDepthStencilState.stencilReadMask ); glStencilOp( static_cast(m_glDepthStencilState.stencilFailOp), static_cast(m_glDepthStencilState.stencilDepthFailOp), static_cast(m_glDepthStencilState.stencilDepthPassOp) ); } else { glDisable(GL_STENCIL_TEST); } } void OpenGLPipelineState::ApplyBlend() { if (m_glBlendState.blendEnable) { glEnable(GL_BLEND); glBlendFuncSeparate( static_cast(m_glBlendState.srcBlend), static_cast(m_glBlendState.dstBlend), static_cast(m_glBlendState.srcBlendAlpha), static_cast(m_glBlendState.dstBlendAlpha) ); glBlendEquationSeparate( static_cast(m_glBlendState.blendOp), static_cast(m_glBlendState.blendOpAlpha) ); glColorMask( (m_glBlendState.colorWriteMask & 1) != 0, (m_glBlendState.colorWriteMask & 2) != 0, (m_glBlendState.colorWriteMask & 4) != 0, (m_glBlendState.colorWriteMask & 8) != 0 ); } else { glDisable(GL_BLEND); } } void OpenGLPipelineState::ApplyRasterizer() { if (m_glRasterizerState.cullFaceEnable) { glEnable(GL_CULL_FACE); glCullFace(static_cast(m_glRasterizerState.cullFace)); glFrontFace(static_cast(m_glRasterizerState.frontFace)); } else { glDisable(GL_CULL_FACE); } glPolygonMode(GL_FRONT_AND_BACK, static_cast(m_glRasterizerState.polygonMode)); if (m_glRasterizerState.multisampleEnable) { glEnable(GL_MULTISAMPLE); } else { glDisable(GL_MULTISAMPLE); } } void OpenGLPipelineState::ApplyViewport() { glViewport((GLint)m_viewportState.x, (GLint)m_viewportState.y, (GLsizei)m_viewportState.width, (GLsizei)m_viewportState.height); glDepthRange(m_viewportState.minDepth, m_viewportState.maxDepth); } void OpenGLPipelineState::ApplyScissor() { if (m_scissorState.enable) { glEnable(GL_SCISSOR_TEST); glScissor(m_scissorState.x, m_scissorState.y, m_scissorState.width, m_scissorState.height); } else { glDisable(GL_SCISSOR_TEST); } } void OpenGLPipelineState::SetProgram(unsigned int program) { m_program = program; m_programAttached = (program != 0); } void OpenGLPipelineState::SetDepthStencilState(const OpenGLDepthStencilState& state) { m_glDepthStencilState = state; } void OpenGLPipelineState::SetBlendState(const OpenGLBlendState& state) { m_glBlendState = state; } void OpenGLPipelineState::SetRasterizerState(const OpenGLRasterizerState& state) { m_glRasterizerState = state; } void OpenGLPipelineState::SetViewport(const ViewportState& state) { m_viewportState = state; } void OpenGLPipelineState::SetScissor(const ScissorState& state) { m_scissorState = state; } void OpenGLPipelineState::SetClearColor(float r, float g, float b, float a) { m_clearColor[0] = r; m_clearColor[1] = g; m_clearColor[2] = b; m_clearColor[3] = a; glClearColor(r, g, b, a); } void OpenGLPipelineState::Clear(unsigned int buffers) { unsigned int glBuffers = 0; if (buffers & 1) glBuffers |= GL_COLOR_BUFFER_BIT; if (buffers & 2) glBuffers |= GL_DEPTH_BUFFER_BIT; if (buffers & 4) glBuffers |= GL_STENCIL_BUFFER_BIT; glClear(glBuffers); } void OpenGLPipelineState::AttachShader(unsigned int program) { m_program = program; m_programAttached = true; glUseProgram(program); } void OpenGLPipelineState::DetachShader() { m_program = 0; m_programAttached = false; glUseProgram(0); } const OpenGLDepthStencilState& OpenGLPipelineState::GetOpenGLDepthStencilState() const { return m_glDepthStencilState; } const OpenGLBlendState& OpenGLPipelineState::GetOpenGLBlendState() const { return m_glBlendState; } const OpenGLRasterizerState& OpenGLPipelineState::GetOpenGLRasterizerState() const { return m_glRasterizerState; } } // namespace RHI } // namespace XCEngine