|
|
|
@ -22,17 +22,15 @@ OpenGLState::OpenGLState() {
|
|
|
|
|
depth.test_enabled = false;
|
|
|
|
|
depth.test_func = GL_LESS;
|
|
|
|
|
depth.write_mask = GL_TRUE;
|
|
|
|
|
depth.depth_range_near = 0.0f;
|
|
|
|
|
depth.depth_range_far = 1.0f;
|
|
|
|
|
|
|
|
|
|
primitive_restart.enabled = false;
|
|
|
|
|
primitive_restart.index = 0;
|
|
|
|
|
|
|
|
|
|
color_mask.red_enabled = GL_TRUE;
|
|
|
|
|
color_mask.green_enabled = GL_TRUE;
|
|
|
|
|
color_mask.blue_enabled = GL_TRUE;
|
|
|
|
|
color_mask.alpha_enabled = GL_TRUE;
|
|
|
|
|
|
|
|
|
|
for (auto& item : color_mask) {
|
|
|
|
|
item.red_enabled = GL_TRUE;
|
|
|
|
|
item.green_enabled = GL_TRUE;
|
|
|
|
|
item.blue_enabled = GL_TRUE;
|
|
|
|
|
item.alpha_enabled = GL_TRUE;
|
|
|
|
|
}
|
|
|
|
|
stencil.test_enabled = false;
|
|
|
|
|
auto reset_stencil = [](auto& config) {
|
|
|
|
|
config.test_func = GL_ALWAYS;
|
|
|
|
@ -45,19 +43,33 @@ OpenGLState::OpenGLState() {
|
|
|
|
|
};
|
|
|
|
|
reset_stencil(stencil.front);
|
|
|
|
|
reset_stencil(stencil.back);
|
|
|
|
|
|
|
|
|
|
blend.enabled = true;
|
|
|
|
|
blend.rgb_equation = GL_FUNC_ADD;
|
|
|
|
|
blend.a_equation = GL_FUNC_ADD;
|
|
|
|
|
blend.src_rgb_func = GL_ONE;
|
|
|
|
|
blend.dst_rgb_func = GL_ZERO;
|
|
|
|
|
blend.src_a_func = GL_ONE;
|
|
|
|
|
blend.dst_a_func = GL_ZERO;
|
|
|
|
|
blend.color.red = 0.0f;
|
|
|
|
|
blend.color.green = 0.0f;
|
|
|
|
|
blend.color.blue = 0.0f;
|
|
|
|
|
blend.color.alpha = 0.0f;
|
|
|
|
|
|
|
|
|
|
for (auto& item : viewports) {
|
|
|
|
|
item.x = 0;
|
|
|
|
|
item.y = 0;
|
|
|
|
|
item.width = 0;
|
|
|
|
|
item.height = 0;
|
|
|
|
|
item.depth_range_near = 0.0f;
|
|
|
|
|
item.depth_range_far = 1.0f;
|
|
|
|
|
}
|
|
|
|
|
scissor.enabled = false;
|
|
|
|
|
scissor.x = 0;
|
|
|
|
|
scissor.y = 0;
|
|
|
|
|
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.operation = GL_COPY;
|
|
|
|
|
|
|
|
|
@ -73,17 +85,6 @@ OpenGLState::OpenGLState() {
|
|
|
|
|
draw.shader_program = 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 = {};
|
|
|
|
|
|
|
|
|
|
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 {
|
|
|
|
|
// Depth test
|
|
|
|
|
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) {
|
|
|
|
|
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 {
|
|
|
|
@ -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;
|
|
|
|
|
if (scissor_changed) {
|
|
|
|
|
if (scissor.enabled) {
|
|
|
|
@ -217,51 +239,141 @@ void OpenGLState::ApplyScissorTest() const {
|
|
|
|
|
glDisable(GL_SCISSOR_TEST);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (scissor_changed || scissor_changed || scissor.x != cur_state.scissor.x ||
|
|
|
|
|
scissor.y != cur_state.scissor.y || scissor.width != cur_state.scissor.width ||
|
|
|
|
|
scissor.height != cur_state.scissor.height) {
|
|
|
|
|
if (scissor.enabled &&
|
|
|
|
|
(scissor_changed || scissor.x != cur_state.scissor.x || scissor.y != cur_state.scissor.y ||
|
|
|
|
|
scissor.width != cur_state.scissor.width || scissor.height != cur_state.scissor.height)) {
|
|
|
|
|
glScissor(scissor.x, scissor.y, scissor.width, scissor.height);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OpenGLState::ApplyBlending() const {
|
|
|
|
|
const bool blend_changed = blend.enabled != cur_state.blend.enabled;
|
|
|
|
|
void OpenGLState::ApplyViewport() const {
|
|
|
|
|
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.enabled) {
|
|
|
|
|
ASSERT(!logic_op.enabled);
|
|
|
|
|
if (updated.enabled) {
|
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
|
} else {
|
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (blend.enabled) {
|
|
|
|
|
if (blend_changed || 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);
|
|
|
|
|
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) {
|
|
|
|
|
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 ||
|
|
|
|
|
blend.dst_rgb_func != cur_state.blend.dst_rgb_func ||
|
|
|
|
|
blend.src_a_func != cur_state.blend.src_a_func ||
|
|
|
|
|
blend.dst_a_func != cur_state.blend.dst_a_func) {
|
|
|
|
|
glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func,
|
|
|
|
|
blend.dst_a_func);
|
|
|
|
|
if (blend_changed || updated.rgb_equation != current.rgb_equation ||
|
|
|
|
|
updated.a_equation != current.a_equation) {
|
|
|
|
|
glBlendEquationSeparate(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) {
|
|
|
|
|
glBlendFunc(updated.src_rgb_func, updated.dst_rgb_func);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (blend_changed || blend.rgb_equation != cur_state.blend.rgb_equation ||
|
|
|
|
|
blend.a_equation != cur_state.blend.a_equation) {
|
|
|
|
|
glBlendEquationSeparate(blend.rgb_equation, blend.a_equation);
|
|
|
|
|
if (blend_changed || updated.rgb_equation != current.rgb_equation) {
|
|
|
|
|
glBlendEquation(updated.rgb_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 {
|
|
|
|
|
const bool logic_op_changed = logic_op.enabled != cur_state.logic_op.enabled;
|
|
|
|
|
if (logic_op_changed) {
|
|
|
|
|
if (logic_op.enabled) {
|
|
|
|
|
ASSERT(!blend.enabled);
|
|
|
|
|
glEnable(GL_COLOR_LOGIC_OP);
|
|
|
|
|
} else {
|
|
|
|
|
glDisable(GL_COLOR_LOGIC_OP);
|
|
|
|
@ -348,12 +460,6 @@ void OpenGLState::Apply() const {
|
|
|
|
|
if (draw.program_pipeline != cur_state.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
|
|
|
|
|
for (std::size_t i = 0; i < clip_distance.size(); ++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
|
|
|
|
|
if (point.size != cur_state.point.size) {
|
|
|
|
|
glPointSize(point.size);
|
|
|
|
|
}
|
|
|
|
|
ApplyScissorTest();
|
|
|
|
|
ApplyColorMask();
|
|
|
|
|
ApplyViewport();
|
|
|
|
|
ApplyScissor();
|
|
|
|
|
ApplyStencilTest();
|
|
|
|
|
ApplySRgb();
|
|
|
|
|
ApplyCulling();
|
|
|
|
|