Merge pull request #1635 from Tinob/master
Implement multi-target viewports and blending
This commit is contained in:
commit
74bce4d68f
6 changed files with 337 additions and 152 deletions
|
@ -37,6 +37,22 @@ void Maxwell3D::InitializeRegisterDefaults() {
|
||||||
regs.viewport[viewport].depth_range_near = 0.0f;
|
regs.viewport[viewport].depth_range_near = 0.0f;
|
||||||
regs.viewport[viewport].depth_range_far = 1.0f;
|
regs.viewport[viewport].depth_range_far = 1.0f;
|
||||||
}
|
}
|
||||||
|
// Doom and Bomberman seems to use the uninitialized registers and just enable blend
|
||||||
|
// so initialize blend registers with sane values
|
||||||
|
regs.blend.equation_rgb = Regs::Blend::Equation::Add;
|
||||||
|
regs.blend.factor_source_rgb = Regs::Blend::Factor::One;
|
||||||
|
regs.blend.factor_dest_rgb = Regs::Blend::Factor::Zero;
|
||||||
|
regs.blend.equation_a = Regs::Blend::Equation::Add;
|
||||||
|
regs.blend.factor_source_a = Regs::Blend::Factor::One;
|
||||||
|
regs.blend.factor_dest_a = Regs::Blend::Factor::Zero;
|
||||||
|
for (std::size_t blend_index = 0; blend_index < Regs::NumRenderTargets; blend_index++) {
|
||||||
|
regs.independent_blend[blend_index].equation_rgb = Regs::Blend::Equation::Add;
|
||||||
|
regs.independent_blend[blend_index].factor_source_rgb = Regs::Blend::Factor::One;
|
||||||
|
regs.independent_blend[blend_index].factor_dest_rgb = Regs::Blend::Factor::Zero;
|
||||||
|
regs.independent_blend[blend_index].equation_a = Regs::Blend::Equation::Add;
|
||||||
|
regs.independent_blend[blend_index].factor_source_a = Regs::Blend::Factor::One;
|
||||||
|
regs.independent_blend[blend_index].factor_dest_a = Regs::Blend::Factor::Zero;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
|
void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
|
||||||
|
|
|
@ -462,6 +462,16 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ColorMask {
|
||||||
|
union {
|
||||||
|
u32 raw;
|
||||||
|
BitField<0, 4, u32> R;
|
||||||
|
BitField<4, 4, u32> G;
|
||||||
|
BitField<8, 4, u32> B;
|
||||||
|
BitField<12, 4, u32> A;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
bool IsShaderConfigEnabled(std::size_t index) const {
|
bool IsShaderConfigEnabled(std::size_t index) const {
|
||||||
// The VertexB is always enabled.
|
// The VertexB is always enabled.
|
||||||
if (index == static_cast<std::size_t>(Regs::ShaderProgram::VertexB)) {
|
if (index == static_cast<std::size_t>(Regs::ShaderProgram::VertexB)) {
|
||||||
|
@ -571,7 +581,11 @@ public:
|
||||||
u32 stencil_back_mask;
|
u32 stencil_back_mask;
|
||||||
u32 stencil_back_func_mask;
|
u32 stencil_back_func_mask;
|
||||||
|
|
||||||
INSERT_PADDING_WORDS(0x13);
|
INSERT_PADDING_WORDS(0xC);
|
||||||
|
|
||||||
|
u32 color_mask_common;
|
||||||
|
|
||||||
|
INSERT_PADDING_WORDS(0x6);
|
||||||
|
|
||||||
u32 rt_separate_frag_data;
|
u32 rt_separate_frag_data;
|
||||||
|
|
||||||
|
@ -646,8 +660,14 @@ public:
|
||||||
ComparisonOp depth_test_func;
|
ComparisonOp depth_test_func;
|
||||||
float alpha_test_ref;
|
float alpha_test_ref;
|
||||||
ComparisonOp alpha_test_func;
|
ComparisonOp alpha_test_func;
|
||||||
|
u32 draw_tfb_stride;
|
||||||
INSERT_PADDING_WORDS(0x9);
|
struct {
|
||||||
|
float r;
|
||||||
|
float g;
|
||||||
|
float b;
|
||||||
|
float a;
|
||||||
|
} blend_color;
|
||||||
|
INSERT_PADDING_WORDS(0x4);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u32 separate_alpha;
|
u32 separate_alpha;
|
||||||
|
@ -841,8 +861,9 @@ public:
|
||||||
BitField<6, 4, u32> RT;
|
BitField<6, 4, u32> RT;
|
||||||
BitField<10, 11, u32> layer;
|
BitField<10, 11, u32> layer;
|
||||||
} clear_buffers;
|
} clear_buffers;
|
||||||
|
INSERT_PADDING_WORDS(0xB);
|
||||||
INSERT_PADDING_WORDS(0x4B);
|
std::array<ColorMask, NumRenderTargets> color_mask;
|
||||||
|
INSERT_PADDING_WORDS(0x38);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u32 query_address_high;
|
u32 query_address_high;
|
||||||
|
@ -1075,6 +1096,7 @@ ASSERT_REG_POSITION(scissor_test, 0x380);
|
||||||
ASSERT_REG_POSITION(stencil_back_func_ref, 0x3D5);
|
ASSERT_REG_POSITION(stencil_back_func_ref, 0x3D5);
|
||||||
ASSERT_REG_POSITION(stencil_back_mask, 0x3D6);
|
ASSERT_REG_POSITION(stencil_back_mask, 0x3D6);
|
||||||
ASSERT_REG_POSITION(stencil_back_func_mask, 0x3D7);
|
ASSERT_REG_POSITION(stencil_back_func_mask, 0x3D7);
|
||||||
|
ASSERT_REG_POSITION(color_mask_common, 0x3E4);
|
||||||
ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB);
|
ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB);
|
||||||
ASSERT_REG_POSITION(zeta, 0x3F8);
|
ASSERT_REG_POSITION(zeta, 0x3F8);
|
||||||
ASSERT_REG_POSITION(vertex_attrib_format, 0x458);
|
ASSERT_REG_POSITION(vertex_attrib_format, 0x458);
|
||||||
|
@ -1087,6 +1109,10 @@ ASSERT_REG_POSITION(depth_write_enabled, 0x4BA);
|
||||||
ASSERT_REG_POSITION(alpha_test_enabled, 0x4BB);
|
ASSERT_REG_POSITION(alpha_test_enabled, 0x4BB);
|
||||||
ASSERT_REG_POSITION(d3d_cull_mode, 0x4C2);
|
ASSERT_REG_POSITION(d3d_cull_mode, 0x4C2);
|
||||||
ASSERT_REG_POSITION(depth_test_func, 0x4C3);
|
ASSERT_REG_POSITION(depth_test_func, 0x4C3);
|
||||||
|
ASSERT_REG_POSITION(alpha_test_ref, 0x4C4);
|
||||||
|
ASSERT_REG_POSITION(alpha_test_func, 0x4C5);
|
||||||
|
ASSERT_REG_POSITION(draw_tfb_stride, 0x4C6);
|
||||||
|
ASSERT_REG_POSITION(blend_color, 0x4C7);
|
||||||
ASSERT_REG_POSITION(blend, 0x4CF);
|
ASSERT_REG_POSITION(blend, 0x4CF);
|
||||||
ASSERT_REG_POSITION(stencil_enable, 0x4E0);
|
ASSERT_REG_POSITION(stencil_enable, 0x4E0);
|
||||||
ASSERT_REG_POSITION(stencil_front_op_fail, 0x4E1);
|
ASSERT_REG_POSITION(stencil_front_op_fail, 0x4E1);
|
||||||
|
@ -1117,6 +1143,7 @@ ASSERT_REG_POSITION(instanced_arrays, 0x620);
|
||||||
ASSERT_REG_POSITION(cull, 0x646);
|
ASSERT_REG_POSITION(cull, 0x646);
|
||||||
ASSERT_REG_POSITION(logic_op, 0x671);
|
ASSERT_REG_POSITION(logic_op, 0x671);
|
||||||
ASSERT_REG_POSITION(clear_buffers, 0x674);
|
ASSERT_REG_POSITION(clear_buffers, 0x674);
|
||||||
|
ASSERT_REG_POSITION(color_mask, 0x680);
|
||||||
ASSERT_REG_POSITION(query, 0x6C0);
|
ASSERT_REG_POSITION(query, 0x6C0);
|
||||||
ASSERT_REG_POSITION(vertex_array[0], 0x700);
|
ASSERT_REG_POSITION(vertex_array[0], 0x700);
|
||||||
ASSERT_REG_POSITION(independent_blend, 0x780);
|
ASSERT_REG_POSITION(independent_blend, 0x780);
|
||||||
|
|
|
@ -511,10 +511,10 @@ void RasterizerOpenGL::Clear() {
|
||||||
|
|
||||||
OpenGLState clear_state;
|
OpenGLState clear_state;
|
||||||
clear_state.draw.draw_framebuffer = framebuffer.handle;
|
clear_state.draw.draw_framebuffer = framebuffer.handle;
|
||||||
clear_state.color_mask.red_enabled = regs.clear_buffers.R ? GL_TRUE : GL_FALSE;
|
clear_state.color_mask[0].red_enabled = regs.clear_buffers.R ? GL_TRUE : GL_FALSE;
|
||||||
clear_state.color_mask.green_enabled = regs.clear_buffers.G ? GL_TRUE : GL_FALSE;
|
clear_state.color_mask[0].green_enabled = regs.clear_buffers.G ? GL_TRUE : GL_FALSE;
|
||||||
clear_state.color_mask.blue_enabled = regs.clear_buffers.B ? GL_TRUE : GL_FALSE;
|
clear_state.color_mask[0].blue_enabled = regs.clear_buffers.B ? GL_TRUE : GL_FALSE;
|
||||||
clear_state.color_mask.alpha_enabled = regs.clear_buffers.A ? GL_TRUE : GL_FALSE;
|
clear_state.color_mask[0].alpha_enabled = regs.clear_buffers.A ? GL_TRUE : GL_FALSE;
|
||||||
|
|
||||||
if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
|
if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
|
||||||
regs.clear_buffers.A) {
|
regs.clear_buffers.A) {
|
||||||
|
@ -573,14 +573,13 @@ void RasterizerOpenGL::DrawArrays() {
|
||||||
ScopeAcquireGLContext acquire_context{emu_window};
|
ScopeAcquireGLContext acquire_context{emu_window};
|
||||||
|
|
||||||
ConfigureFramebuffers();
|
ConfigureFramebuffers();
|
||||||
|
SyncColorMask();
|
||||||
SyncDepthTestState();
|
SyncDepthTestState();
|
||||||
SyncStencilTestState();
|
SyncStencilTestState();
|
||||||
SyncBlendState();
|
SyncBlendState();
|
||||||
SyncLogicOpState();
|
SyncLogicOpState();
|
||||||
SyncCullMode();
|
SyncCullMode();
|
||||||
SyncPrimitiveRestart();
|
SyncPrimitiveRestart();
|
||||||
SyncDepthRange();
|
|
||||||
SyncScissorTest();
|
SyncScissorTest();
|
||||||
// Alpha Testing is synced on shaders.
|
// Alpha Testing is synced on shaders.
|
||||||
SyncTransformFeedback();
|
SyncTransformFeedback();
|
||||||
|
@ -899,12 +898,16 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncViewport() {
|
void RasterizerOpenGL::SyncViewport() {
|
||||||
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
||||||
const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
|
for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
|
||||||
|
const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[i].GetRect()};
|
||||||
state.viewport.x = viewport_rect.left;
|
auto& viewport = state.viewports[i];
|
||||||
state.viewport.y = viewport_rect.bottom;
|
viewport.x = viewport_rect.left;
|
||||||
state.viewport.width = static_cast<GLsizei>(viewport_rect.GetWidth());
|
viewport.y = viewport_rect.bottom;
|
||||||
state.viewport.height = static_cast<GLsizei>(viewport_rect.GetHeight());
|
viewport.width = static_cast<GLsizei>(viewport_rect.GetWidth());
|
||||||
|
viewport.height = static_cast<GLsizei>(viewport_rect.GetHeight());
|
||||||
|
viewport.depth_range_far = regs.viewport[i].depth_range_far;
|
||||||
|
viewport.depth_range_near = regs.viewport[i].depth_range_near;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncClipEnabled() {
|
void RasterizerOpenGL::SyncClipEnabled() {
|
||||||
|
@ -946,13 +949,6 @@ void RasterizerOpenGL::SyncPrimitiveRestart() {
|
||||||
state.primitive_restart.index = regs.primitive_restart.index;
|
state.primitive_restart.index = regs.primitive_restart.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncDepthRange() {
|
|
||||||
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
|
||||||
|
|
||||||
state.depth.depth_range_near = regs.viewport->depth_range_near;
|
|
||||||
state.depth.depth_range_far = regs.viewport->depth_range_far;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncDepthTestState() {
|
void RasterizerOpenGL::SyncDepthTestState() {
|
||||||
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
||||||
|
|
||||||
|
@ -993,26 +989,60 @@ void RasterizerOpenGL::SyncStencilTestState() {
|
||||||
state.stencil.back.write_mask = regs.stencil_back_mask;
|
state.stencil.back.write_mask = regs.stencil_back_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerOpenGL::SyncColorMask() {
|
||||||
|
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
||||||
|
for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
|
||||||
|
const auto& source = regs.color_mask[regs.color_mask_common ? 0 : i];
|
||||||
|
auto& dest = state.color_mask[i];
|
||||||
|
dest.red_enabled = (source.R == 0) ? GL_FALSE : GL_TRUE;
|
||||||
|
dest.green_enabled = (source.G == 0) ? GL_FALSE : GL_TRUE;
|
||||||
|
dest.blue_enabled = (source.B == 0) ? GL_FALSE : GL_TRUE;
|
||||||
|
dest.alpha_enabled = (source.A == 0) ? GL_FALSE : GL_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncBlendState() {
|
void RasterizerOpenGL::SyncBlendState() {
|
||||||
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
||||||
|
|
||||||
// TODO(Subv): Support more than just render target 0.
|
state.blend_color.red = regs.blend_color.r;
|
||||||
state.blend.enabled = regs.blend.enable[0] != 0;
|
state.blend_color.green = regs.blend_color.g;
|
||||||
|
state.blend_color.blue = regs.blend_color.b;
|
||||||
|
state.blend_color.alpha = regs.blend_color.a;
|
||||||
|
|
||||||
if (!state.blend.enabled)
|
state.independant_blend.enabled = regs.independent_blend_enable;
|
||||||
|
if (!state.independant_blend.enabled) {
|
||||||
|
auto& blend = state.blend[0];
|
||||||
|
blend.enabled = regs.blend.enable[0] != 0;
|
||||||
|
blend.separate_alpha = regs.blend.separate_alpha;
|
||||||
|
blend.rgb_equation = MaxwellToGL::BlendEquation(regs.blend.equation_rgb);
|
||||||
|
blend.src_rgb_func = MaxwellToGL::BlendFunc(regs.blend.factor_source_rgb);
|
||||||
|
blend.dst_rgb_func = MaxwellToGL::BlendFunc(regs.blend.factor_dest_rgb);
|
||||||
|
if (blend.separate_alpha) {
|
||||||
|
blend.a_equation = MaxwellToGL::BlendEquation(regs.blend.equation_a);
|
||||||
|
blend.src_a_func = MaxwellToGL::BlendFunc(regs.blend.factor_source_a);
|
||||||
|
blend.dst_a_func = MaxwellToGL::BlendFunc(regs.blend.factor_dest_a);
|
||||||
|
}
|
||||||
|
for (size_t i = 1; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
|
||||||
|
state.blend[i].enabled = false;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT_MSG(regs.logic_op.enable == 0,
|
for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
|
||||||
"Blending and logic op can't be enabled at the same time.");
|
auto& blend = state.blend[i];
|
||||||
|
blend.enabled = regs.blend.enable[i] != 0;
|
||||||
ASSERT_MSG(regs.independent_blend_enable == 1, "Only independent blending is implemented");
|
if (!blend.enabled)
|
||||||
ASSERT_MSG(!regs.independent_blend[0].separate_alpha, "Unimplemented");
|
continue;
|
||||||
state.blend.rgb_equation = MaxwellToGL::BlendEquation(regs.independent_blend[0].equation_rgb);
|
blend.separate_alpha = regs.independent_blend[i].separate_alpha;
|
||||||
state.blend.src_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_source_rgb);
|
blend.rgb_equation = MaxwellToGL::BlendEquation(regs.independent_blend[i].equation_rgb);
|
||||||
state.blend.dst_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_dest_rgb);
|
blend.src_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[i].factor_source_rgb);
|
||||||
state.blend.a_equation = MaxwellToGL::BlendEquation(regs.independent_blend[0].equation_a);
|
blend.dst_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[i].factor_dest_rgb);
|
||||||
state.blend.src_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_source_a);
|
if (blend.separate_alpha) {
|
||||||
state.blend.dst_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_dest_a);
|
blend.a_equation = MaxwellToGL::BlendEquation(regs.independent_blend[i].equation_a);
|
||||||
|
blend.src_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[i].factor_source_a);
|
||||||
|
blend.dst_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[i].factor_dest_a);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncLogicOpState() {
|
void RasterizerOpenGL::SyncLogicOpState() {
|
||||||
|
@ -1031,19 +1061,19 @@ void RasterizerOpenGL::SyncLogicOpState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncScissorTest() {
|
void RasterizerOpenGL::SyncScissorTest() {
|
||||||
|
// TODO: what is the correct behavior here, a single scissor for all targets
|
||||||
|
// or scissor disabled for the rest of the targets?
|
||||||
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
||||||
|
|
||||||
state.scissor.enabled = (regs.scissor_test.enable != 0);
|
state.scissor.enabled = (regs.scissor_test.enable != 0);
|
||||||
// TODO(Blinkhawk): Figure if the hardware supports scissor testing per viewport and how it's
|
if (regs.scissor_test.enable == 0) {
|
||||||
// implemented.
|
return;
|
||||||
if (regs.scissor_test.enable != 0) {
|
}
|
||||||
const u32 width = regs.scissor_test.max_x - regs.scissor_test.min_x;
|
const u32 width = regs.scissor_test.max_x - regs.scissor_test.min_x;
|
||||||
const u32 height = regs.scissor_test.max_y - regs.scissor_test.min_y;
|
const u32 height = regs.scissor_test.max_y - regs.scissor_test.min_y;
|
||||||
state.scissor.x = regs.scissor_test.min_x;
|
state.scissor.x = regs.scissor_test.min_x;
|
||||||
state.scissor.y = regs.scissor_test.min_y;
|
state.scissor.y = regs.scissor_test.min_y;
|
||||||
state.scissor.width = width;
|
state.scissor.width = width;
|
||||||
state.scissor.height = height;
|
state.scissor.height = height;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncTransformFeedback() {
|
void RasterizerOpenGL::SyncTransformFeedback() {
|
||||||
|
|
|
@ -133,7 +133,7 @@ private:
|
||||||
u32 SetupTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, Shader& shader,
|
u32 SetupTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, Shader& shader,
|
||||||
GLenum primitive_mode, u32 current_unit);
|
GLenum primitive_mode, u32 current_unit);
|
||||||
|
|
||||||
/// Syncs the viewport to match the guest state
|
/// Syncs the viewport and depth range to match the guest state
|
||||||
void SyncViewport();
|
void SyncViewport();
|
||||||
|
|
||||||
/// Syncs the clip enabled status to match the guest state
|
/// Syncs the clip enabled status to match the guest state
|
||||||
|
@ -148,9 +148,6 @@ private:
|
||||||
/// Syncs the primitve restart to match the guest state
|
/// Syncs the primitve restart to match the guest state
|
||||||
void SyncPrimitiveRestart();
|
void SyncPrimitiveRestart();
|
||||||
|
|
||||||
/// Syncs the depth range to match the guest state
|
|
||||||
void SyncDepthRange();
|
|
||||||
|
|
||||||
/// Syncs the depth test state to match the guest state
|
/// Syncs the depth test state to match the guest state
|
||||||
void SyncDepthTestState();
|
void SyncDepthTestState();
|
||||||
|
|
||||||
|
@ -172,6 +169,9 @@ private:
|
||||||
/// Syncs the point state to match the guest state
|
/// Syncs the point state to match the guest state
|
||||||
void SyncPointState();
|
void SyncPointState();
|
||||||
|
|
||||||
|
/// Syncs Color Mask
|
||||||
|
void SyncColorMask();
|
||||||
|
|
||||||
/// Check asserts for alpha testing.
|
/// Check asserts for alpha testing.
|
||||||
void CheckAlphaTests();
|
void CheckAlphaTests();
|
||||||
|
|
||||||
|
|
|
@ -22,17 +22,15 @@ OpenGLState::OpenGLState() {
|
||||||
depth.test_enabled = false;
|
depth.test_enabled = false;
|
||||||
depth.test_func = GL_LESS;
|
depth.test_func = GL_LESS;
|
||||||
depth.write_mask = GL_TRUE;
|
depth.write_mask = GL_TRUE;
|
||||||
depth.depth_range_near = 0.0f;
|
|
||||||
depth.depth_range_far = 1.0f;
|
|
||||||
|
|
||||||
primitive_restart.enabled = false;
|
primitive_restart.enabled = false;
|
||||||
primitive_restart.index = 0;
|
primitive_restart.index = 0;
|
||||||
|
for (auto& item : color_mask) {
|
||||||
color_mask.red_enabled = GL_TRUE;
|
item.red_enabled = GL_TRUE;
|
||||||
color_mask.green_enabled = GL_TRUE;
|
item.green_enabled = GL_TRUE;
|
||||||
color_mask.blue_enabled = GL_TRUE;
|
item.blue_enabled = GL_TRUE;
|
||||||
color_mask.alpha_enabled = GL_TRUE;
|
item.alpha_enabled = GL_TRUE;
|
||||||
|
}
|
||||||
stencil.test_enabled = false;
|
stencil.test_enabled = false;
|
||||||
auto reset_stencil = [](auto& config) {
|
auto reset_stencil = [](auto& config) {
|
||||||
config.test_func = GL_ALWAYS;
|
config.test_func = GL_ALWAYS;
|
||||||
|
@ -45,19 +43,33 @@ OpenGLState::OpenGLState() {
|
||||||
};
|
};
|
||||||
reset_stencil(stencil.front);
|
reset_stencil(stencil.front);
|
||||||
reset_stencil(stencil.back);
|
reset_stencil(stencil.back);
|
||||||
|
for (auto& item : viewports) {
|
||||||
blend.enabled = true;
|
item.x = 0;
|
||||||
blend.rgb_equation = GL_FUNC_ADD;
|
item.y = 0;
|
||||||
blend.a_equation = GL_FUNC_ADD;
|
item.width = 0;
|
||||||
blend.src_rgb_func = GL_ONE;
|
item.height = 0;
|
||||||
blend.dst_rgb_func = GL_ZERO;
|
item.depth_range_near = 0.0f;
|
||||||
blend.src_a_func = GL_ONE;
|
item.depth_range_far = 1.0f;
|
||||||
blend.dst_a_func = GL_ZERO;
|
}
|
||||||
blend.color.red = 0.0f;
|
scissor.enabled = false;
|
||||||
blend.color.green = 0.0f;
|
scissor.x = 0;
|
||||||
blend.color.blue = 0.0f;
|
scissor.y = 0;
|
||||||
blend.color.alpha = 0.0f;
|
scissor.width = 0;
|
||||||
|
scissor.height = 0;
|
||||||
|
for (auto& item : blend) {
|
||||||
|
item.enabled = true;
|
||||||
|
item.rgb_equation = GL_FUNC_ADD;
|
||||||
|
item.a_equation = GL_FUNC_ADD;
|
||||||
|
item.src_rgb_func = GL_ONE;
|
||||||
|
item.dst_rgb_func = GL_ZERO;
|
||||||
|
item.src_a_func = GL_ONE;
|
||||||
|
item.dst_a_func = GL_ZERO;
|
||||||
|
}
|
||||||
|
independant_blend.enabled = false;
|
||||||
|
blend_color.red = 0.0f;
|
||||||
|
blend_color.green = 0.0f;
|
||||||
|
blend_color.blue = 0.0f;
|
||||||
|
blend_color.alpha = 0.0f;
|
||||||
logic_op.enabled = false;
|
logic_op.enabled = false;
|
||||||
logic_op.operation = GL_COPY;
|
logic_op.operation = GL_COPY;
|
||||||
|
|
||||||
|
@ -73,17 +85,6 @@ OpenGLState::OpenGLState() {
|
||||||
draw.shader_program = 0;
|
draw.shader_program = 0;
|
||||||
draw.program_pipeline = 0;
|
draw.program_pipeline = 0;
|
||||||
|
|
||||||
scissor.enabled = false;
|
|
||||||
scissor.x = 0;
|
|
||||||
scissor.y = 0;
|
|
||||||
scissor.width = 0;
|
|
||||||
scissor.height = 0;
|
|
||||||
|
|
||||||
viewport.x = 0;
|
|
||||||
viewport.y = 0;
|
|
||||||
viewport.width = 0;
|
|
||||||
viewport.height = 0;
|
|
||||||
|
|
||||||
clip_distance = {};
|
clip_distance = {};
|
||||||
|
|
||||||
point.size = 1;
|
point.size = 1;
|
||||||
|
@ -134,6 +135,32 @@ void OpenGLState::ApplyCulling() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLState::ApplyColorMask() const {
|
||||||
|
if (GLAD_GL_ARB_viewport_array) {
|
||||||
|
for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
|
||||||
|
const auto& updated = color_mask[i];
|
||||||
|
const auto& current = cur_state.color_mask[i];
|
||||||
|
if (updated.red_enabled != current.red_enabled ||
|
||||||
|
updated.green_enabled != current.green_enabled ||
|
||||||
|
updated.blue_enabled != current.blue_enabled ||
|
||||||
|
updated.alpha_enabled != current.alpha_enabled) {
|
||||||
|
glColorMaski(static_cast<GLuint>(i), updated.red_enabled, updated.green_enabled,
|
||||||
|
updated.blue_enabled, updated.alpha_enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const auto& updated = color_mask[0];
|
||||||
|
const auto& current = cur_state.color_mask[0];
|
||||||
|
if (updated.red_enabled != current.red_enabled ||
|
||||||
|
updated.green_enabled != current.green_enabled ||
|
||||||
|
updated.blue_enabled != current.blue_enabled ||
|
||||||
|
updated.alpha_enabled != current.alpha_enabled) {
|
||||||
|
glColorMask(updated.red_enabled, updated.green_enabled, updated.blue_enabled,
|
||||||
|
updated.alpha_enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLState::ApplyDepth() const {
|
void OpenGLState::ApplyDepth() const {
|
||||||
// Depth test
|
// Depth test
|
||||||
const bool depth_test_changed = depth.test_enabled != cur_state.depth.test_enabled;
|
const bool depth_test_changed = depth.test_enabled != cur_state.depth.test_enabled;
|
||||||
|
@ -152,11 +179,6 @@ void OpenGLState::ApplyDepth() const {
|
||||||
if (depth.write_mask != cur_state.depth.write_mask) {
|
if (depth.write_mask != cur_state.depth.write_mask) {
|
||||||
glDepthMask(depth.write_mask);
|
glDepthMask(depth.write_mask);
|
||||||
}
|
}
|
||||||
// Depth range
|
|
||||||
if (depth.depth_range_near != cur_state.depth.depth_range_near ||
|
|
||||||
depth.depth_range_far != cur_state.depth.depth_range_far) {
|
|
||||||
glDepthRange(depth.depth_range_near, depth.depth_range_far);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLState::ApplyPrimitiveRestart() const {
|
void OpenGLState::ApplyPrimitiveRestart() const {
|
||||||
|
@ -208,7 +230,7 @@ void OpenGLState::ApplyStencilTest() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLState::ApplyScissorTest() const {
|
void OpenGLState::ApplyScissor() const {
|
||||||
const bool scissor_changed = scissor.enabled != cur_state.scissor.enabled;
|
const bool scissor_changed = scissor.enabled != cur_state.scissor.enabled;
|
||||||
if (scissor_changed) {
|
if (scissor_changed) {
|
||||||
if (scissor.enabled) {
|
if (scissor.enabled) {
|
||||||
|
@ -217,51 +239,141 @@ void OpenGLState::ApplyScissorTest() const {
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (scissor_changed || scissor_changed || scissor.x != cur_state.scissor.x ||
|
if (scissor.enabled &&
|
||||||
scissor.y != cur_state.scissor.y || scissor.width != cur_state.scissor.width ||
|
(scissor_changed || scissor.x != cur_state.scissor.x || scissor.y != cur_state.scissor.y ||
|
||||||
scissor.height != cur_state.scissor.height) {
|
scissor.width != cur_state.scissor.width || scissor.height != cur_state.scissor.height)) {
|
||||||
glScissor(scissor.x, scissor.y, scissor.width, scissor.height);
|
glScissor(scissor.x, scissor.y, scissor.width, scissor.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLState::ApplyBlending() const {
|
void OpenGLState::ApplyViewport() const {
|
||||||
const bool blend_changed = blend.enabled != cur_state.blend.enabled;
|
if (GLAD_GL_ARB_viewport_array) {
|
||||||
|
for (GLuint i = 0;
|
||||||
|
i < static_cast<GLuint>(Tegra::Engines::Maxwell3D::Regs::NumRenderTargets); i++) {
|
||||||
|
const auto& current = cur_state.viewports[i];
|
||||||
|
const auto& updated = viewports[i];
|
||||||
|
if (updated.x != current.x || updated.y != current.y ||
|
||||||
|
updated.width != current.width || updated.height != current.height) {
|
||||||
|
glViewportIndexedf(i, updated.x, updated.y, updated.width, updated.height);
|
||||||
|
}
|
||||||
|
if (updated.depth_range_near != current.depth_range_near ||
|
||||||
|
updated.depth_range_far != current.depth_range_far) {
|
||||||
|
glDepthRangeIndexed(i, updated.depth_range_near, updated.depth_range_far);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const auto& current = cur_state.viewports[0];
|
||||||
|
const auto& updated = viewports[0];
|
||||||
|
if (updated.x != current.x || updated.y != current.y || updated.width != current.width ||
|
||||||
|
updated.height != current.height) {
|
||||||
|
glViewport(updated.x, updated.y, updated.width, updated.height);
|
||||||
|
}
|
||||||
|
if (updated.depth_range_near != current.depth_range_near ||
|
||||||
|
updated.depth_range_far != current.depth_range_far) {
|
||||||
|
glDepthRange(updated.depth_range_near, updated.depth_range_far);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLState::ApplyGlobalBlending() const {
|
||||||
|
const Blend& current = cur_state.blend[0];
|
||||||
|
const Blend& updated = blend[0];
|
||||||
|
const bool blend_changed = updated.enabled != current.enabled;
|
||||||
if (blend_changed) {
|
if (blend_changed) {
|
||||||
if (blend.enabled) {
|
if (updated.enabled) {
|
||||||
ASSERT(!logic_op.enabled);
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
} else {
|
} else {
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (blend.enabled) {
|
if (!updated.enabled) {
|
||||||
if (blend_changed || blend.color.red != cur_state.blend.color.red ||
|
return;
|
||||||
blend.color.green != cur_state.blend.color.green ||
|
}
|
||||||
blend.color.blue != cur_state.blend.color.blue ||
|
if (updated.separate_alpha) {
|
||||||
blend.color.alpha != cur_state.blend.color.alpha) {
|
if (blend_changed || updated.src_rgb_func != current.src_rgb_func ||
|
||||||
glBlendColor(blend.color.red, blend.color.green, blend.color.blue, blend.color.alpha);
|
updated.dst_rgb_func != current.dst_rgb_func ||
|
||||||
|
updated.src_a_func != current.src_a_func || updated.dst_a_func != current.dst_a_func) {
|
||||||
|
glBlendFuncSeparate(updated.src_rgb_func, updated.dst_rgb_func, updated.src_a_func,
|
||||||
|
updated.dst_a_func);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blend_changed || blend.src_rgb_func != cur_state.blend.src_rgb_func ||
|
if (blend_changed || updated.rgb_equation != current.rgb_equation ||
|
||||||
blend.dst_rgb_func != cur_state.blend.dst_rgb_func ||
|
updated.a_equation != current.a_equation) {
|
||||||
blend.src_a_func != cur_state.blend.src_a_func ||
|
glBlendEquationSeparate(updated.rgb_equation, updated.a_equation);
|
||||||
blend.dst_a_func != cur_state.blend.dst_a_func) {
|
}
|
||||||
glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func,
|
} else {
|
||||||
blend.dst_a_func);
|
if (blend_changed || updated.src_rgb_func != current.src_rgb_func ||
|
||||||
|
updated.dst_rgb_func != current.dst_rgb_func) {
|
||||||
|
glBlendFunc(updated.src_rgb_func, updated.dst_rgb_func);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blend_changed || blend.rgb_equation != cur_state.blend.rgb_equation ||
|
if (blend_changed || updated.rgb_equation != current.rgb_equation) {
|
||||||
blend.a_equation != cur_state.blend.a_equation) {
|
glBlendEquation(updated.rgb_equation);
|
||||||
glBlendEquationSeparate(blend.rgb_equation, blend.a_equation);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLState::ApplyTargetBlending(int target, bool force) const {
|
||||||
|
const Blend& updated = blend[target];
|
||||||
|
const Blend& current = cur_state.blend[target];
|
||||||
|
const bool blend_changed = updated.enabled != current.enabled || force;
|
||||||
|
if (blend_changed) {
|
||||||
|
if (updated.enabled) {
|
||||||
|
glEnablei(GL_BLEND, static_cast<GLuint>(target));
|
||||||
|
} else {
|
||||||
|
glDisablei(GL_BLEND, static_cast<GLuint>(target));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!updated.enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (updated.separate_alpha) {
|
||||||
|
if (blend_changed || updated.src_rgb_func != current.src_rgb_func ||
|
||||||
|
updated.dst_rgb_func != current.dst_rgb_func ||
|
||||||
|
updated.src_a_func != current.src_a_func || updated.dst_a_func != current.dst_a_func) {
|
||||||
|
glBlendFuncSeparateiARB(static_cast<GLuint>(target), updated.src_rgb_func,
|
||||||
|
updated.dst_rgb_func, updated.src_a_func, updated.dst_a_func);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blend_changed || updated.rgb_equation != current.rgb_equation ||
|
||||||
|
updated.a_equation != current.a_equation) {
|
||||||
|
glBlendEquationSeparateiARB(static_cast<GLuint>(target), updated.rgb_equation,
|
||||||
|
updated.a_equation);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (blend_changed || updated.src_rgb_func != current.src_rgb_func ||
|
||||||
|
updated.dst_rgb_func != current.dst_rgb_func) {
|
||||||
|
glBlendFunciARB(static_cast<GLuint>(target), updated.src_rgb_func,
|
||||||
|
updated.dst_rgb_func);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blend_changed || updated.rgb_equation != current.rgb_equation) {
|
||||||
|
glBlendEquationiARB(static_cast<GLuint>(target), updated.rgb_equation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLState::ApplyBlending() const {
|
||||||
|
if (independant_blend.enabled) {
|
||||||
|
for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
|
||||||
|
ApplyTargetBlending(i,
|
||||||
|
independant_blend.enabled != cur_state.independant_blend.enabled);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ApplyGlobalBlending();
|
||||||
|
}
|
||||||
|
if (blend_color.red != cur_state.blend_color.red ||
|
||||||
|
blend_color.green != cur_state.blend_color.green ||
|
||||||
|
blend_color.blue != cur_state.blend_color.blue ||
|
||||||
|
blend_color.alpha != cur_state.blend_color.alpha) {
|
||||||
|
glBlendColor(blend_color.red, blend_color.green, blend_color.blue, blend_color.alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLState::ApplyLogicOp() const {
|
void OpenGLState::ApplyLogicOp() const {
|
||||||
const bool logic_op_changed = logic_op.enabled != cur_state.logic_op.enabled;
|
const bool logic_op_changed = logic_op.enabled != cur_state.logic_op.enabled;
|
||||||
if (logic_op_changed) {
|
if (logic_op_changed) {
|
||||||
if (logic_op.enabled) {
|
if (logic_op.enabled) {
|
||||||
ASSERT(!blend.enabled);
|
|
||||||
glEnable(GL_COLOR_LOGIC_OP);
|
glEnable(GL_COLOR_LOGIC_OP);
|
||||||
} else {
|
} else {
|
||||||
glDisable(GL_COLOR_LOGIC_OP);
|
glDisable(GL_COLOR_LOGIC_OP);
|
||||||
|
@ -348,12 +460,6 @@ void OpenGLState::Apply() const {
|
||||||
if (draw.program_pipeline != cur_state.draw.program_pipeline) {
|
if (draw.program_pipeline != cur_state.draw.program_pipeline) {
|
||||||
glBindProgramPipeline(draw.program_pipeline);
|
glBindProgramPipeline(draw.program_pipeline);
|
||||||
}
|
}
|
||||||
// Viewport
|
|
||||||
if (viewport.x != cur_state.viewport.x || viewport.y != cur_state.viewport.y ||
|
|
||||||
viewport.width != cur_state.viewport.width ||
|
|
||||||
viewport.height != cur_state.viewport.height) {
|
|
||||||
glViewport(viewport.x, viewport.y, viewport.width, viewport.height);
|
|
||||||
}
|
|
||||||
// Clip distance
|
// Clip distance
|
||||||
for (std::size_t i = 0; i < clip_distance.size(); ++i) {
|
for (std::size_t i = 0; i < clip_distance.size(); ++i) {
|
||||||
if (clip_distance[i] != cur_state.clip_distance[i]) {
|
if (clip_distance[i] != cur_state.clip_distance[i]) {
|
||||||
|
@ -364,19 +470,13 @@ void OpenGLState::Apply() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Color mask
|
|
||||||
if (color_mask.red_enabled != cur_state.color_mask.red_enabled ||
|
|
||||||
color_mask.green_enabled != cur_state.color_mask.green_enabled ||
|
|
||||||
color_mask.blue_enabled != cur_state.color_mask.blue_enabled ||
|
|
||||||
color_mask.alpha_enabled != cur_state.color_mask.alpha_enabled) {
|
|
||||||
glColorMask(color_mask.red_enabled, color_mask.green_enabled, color_mask.blue_enabled,
|
|
||||||
color_mask.alpha_enabled);
|
|
||||||
}
|
|
||||||
// Point
|
// Point
|
||||||
if (point.size != cur_state.point.size) {
|
if (point.size != cur_state.point.size) {
|
||||||
glPointSize(point.size);
|
glPointSize(point.size);
|
||||||
}
|
}
|
||||||
ApplyScissorTest();
|
ApplyColorMask();
|
||||||
|
ApplyViewport();
|
||||||
|
ApplyScissor();
|
||||||
ApplyStencilTest();
|
ApplyStencilTest();
|
||||||
ApplySRgb();
|
ApplySRgb();
|
||||||
ApplyCulling();
|
ApplyCulling();
|
||||||
|
|
|
@ -49,8 +49,6 @@ public:
|
||||||
bool test_enabled; // GL_DEPTH_TEST
|
bool test_enabled; // GL_DEPTH_TEST
|
||||||
GLenum test_func; // GL_DEPTH_FUNC
|
GLenum test_func; // GL_DEPTH_FUNC
|
||||||
GLboolean write_mask; // GL_DEPTH_WRITEMASK
|
GLboolean write_mask; // GL_DEPTH_WRITEMASK
|
||||||
GLfloat depth_range_near; // GL_DEPTH_RANGE
|
|
||||||
GLfloat depth_range_far; // GL_DEPTH_RANGE
|
|
||||||
} depth;
|
} depth;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -58,13 +56,14 @@ public:
|
||||||
GLuint index;
|
GLuint index;
|
||||||
} primitive_restart; // GL_PRIMITIVE_RESTART
|
} primitive_restart; // GL_PRIMITIVE_RESTART
|
||||||
|
|
||||||
struct {
|
struct ColorMask {
|
||||||
GLboolean red_enabled;
|
GLboolean red_enabled;
|
||||||
GLboolean green_enabled;
|
GLboolean green_enabled;
|
||||||
GLboolean blue_enabled;
|
GLboolean blue_enabled;
|
||||||
GLboolean alpha_enabled;
|
GLboolean alpha_enabled;
|
||||||
} color_mask; // GL_COLOR_WRITEMASK
|
};
|
||||||
|
std::array<ColorMask, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets>
|
||||||
|
color_mask; // GL_COLOR_WRITEMASK
|
||||||
struct {
|
struct {
|
||||||
bool test_enabled; // GL_STENCIL_TEST
|
bool test_enabled; // GL_STENCIL_TEST
|
||||||
struct {
|
struct {
|
||||||
|
@ -78,22 +77,28 @@ public:
|
||||||
} front, back;
|
} front, back;
|
||||||
} stencil;
|
} stencil;
|
||||||
|
|
||||||
struct {
|
struct Blend {
|
||||||
bool enabled; // GL_BLEND
|
bool enabled; // GL_BLEND
|
||||||
|
bool separate_alpha; // Independent blend enabled
|
||||||
GLenum rgb_equation; // GL_BLEND_EQUATION_RGB
|
GLenum rgb_equation; // GL_BLEND_EQUATION_RGB
|
||||||
GLenum a_equation; // GL_BLEND_EQUATION_ALPHA
|
GLenum a_equation; // GL_BLEND_EQUATION_ALPHA
|
||||||
GLenum src_rgb_func; // GL_BLEND_SRC_RGB
|
GLenum src_rgb_func; // GL_BLEND_SRC_RGB
|
||||||
GLenum dst_rgb_func; // GL_BLEND_DST_RGB
|
GLenum dst_rgb_func; // GL_BLEND_DST_RGB
|
||||||
GLenum src_a_func; // GL_BLEND_SRC_ALPHA
|
GLenum src_a_func; // GL_BLEND_SRC_ALPHA
|
||||||
GLenum dst_a_func; // GL_BLEND_DST_ALPHA
|
GLenum dst_a_func; // GL_BLEND_DST_ALPHA
|
||||||
|
};
|
||||||
|
std::array<Blend, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> blend;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool enabled;
|
||||||
|
} independant_blend;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
GLclampf red;
|
GLclampf red;
|
||||||
GLclampf green;
|
GLclampf green;
|
||||||
GLclampf blue;
|
GLclampf blue;
|
||||||
GLclampf alpha;
|
GLclampf alpha;
|
||||||
} color; // GL_BLEND_COLOR
|
} blend_color; // GL_BLEND_COLOR
|
||||||
} blend;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool enabled; // GL_LOGIC_OP_MODE
|
bool enabled; // GL_LOGIC_OP_MODE
|
||||||
|
@ -138,6 +143,16 @@ public:
|
||||||
GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING
|
GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING
|
||||||
} draw;
|
} draw;
|
||||||
|
|
||||||
|
struct viewport {
|
||||||
|
GLfloat x;
|
||||||
|
GLfloat y;
|
||||||
|
GLfloat width;
|
||||||
|
GLfloat height;
|
||||||
|
GLfloat depth_range_near; // GL_DEPTH_RANGE
|
||||||
|
GLfloat depth_range_far; // GL_DEPTH_RANGE
|
||||||
|
};
|
||||||
|
std::array<viewport, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> viewports;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool enabled; // GL_SCISSOR_TEST
|
bool enabled; // GL_SCISSOR_TEST
|
||||||
GLint x;
|
GLint x;
|
||||||
|
@ -146,13 +161,6 @@ public:
|
||||||
GLsizei height;
|
GLsizei height;
|
||||||
} scissor;
|
} scissor;
|
||||||
|
|
||||||
struct {
|
|
||||||
GLint x;
|
|
||||||
GLint y;
|
|
||||||
GLsizei width;
|
|
||||||
GLsizei height;
|
|
||||||
} viewport;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
float size; // GL_POINT_SIZE
|
float size; // GL_POINT_SIZE
|
||||||
} point;
|
} point;
|
||||||
|
@ -191,14 +199,18 @@ private:
|
||||||
static bool s_rgb_used;
|
static bool s_rgb_used;
|
||||||
void ApplySRgb() const;
|
void ApplySRgb() const;
|
||||||
void ApplyCulling() const;
|
void ApplyCulling() const;
|
||||||
|
void ApplyColorMask() const;
|
||||||
void ApplyDepth() const;
|
void ApplyDepth() const;
|
||||||
void ApplyPrimitiveRestart() const;
|
void ApplyPrimitiveRestart() const;
|
||||||
void ApplyStencilTest() const;
|
void ApplyStencilTest() const;
|
||||||
void ApplyScissorTest() const;
|
void ApplyViewport() const;
|
||||||
|
void ApplyTargetBlending(int target, bool force) const;
|
||||||
|
void ApplyGlobalBlending() const;
|
||||||
void ApplyBlending() const;
|
void ApplyBlending() const;
|
||||||
void ApplyLogicOp() const;
|
void ApplyLogicOp() const;
|
||||||
void ApplyTextures() const;
|
void ApplyTextures() const;
|
||||||
void ApplySamplers() const;
|
void ApplySamplers() const;
|
||||||
|
void ApplyScissor() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace OpenGL
|
} // namespace OpenGL
|
||||||
|
|
Loading…
Reference in a new issue