summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp246
-rw-r--r--src/video_core/renderer_opengl/gl_state.h13
3 files changed, 158 insertions, 105 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index bf381271e..8976c77c6 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -104,7 +104,7 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo
104 } 104 }
105 105
106 ASSERT_MSG(has_ARB_separate_shader_objects, "has_ARB_separate_shader_objects is unsupported"); 106 ASSERT_MSG(has_ARB_separate_shader_objects, "has_ARB_separate_shader_objects is unsupported");
107 107 OpenGLState::ApplyDefaultState();
108 // Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0 108 // Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0
109 state.clip_distance[0] = true; 109 state.clip_distance[0] = true;
110 110
@@ -115,8 +115,6 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo
115 state.draw.shader_program = 0; 115 state.draw.shader_program = 0;
116 state.Apply(); 116 state.Apply();
117 117
118 glEnable(GL_BLEND);
119
120 glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniform_buffer_alignment); 118 glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniform_buffer_alignment);
121 119
122 LOG_CRITICAL(Render_OpenGL, "Sync fixed function OpenGL state here!"); 120 LOG_CRITICAL(Render_OpenGL, "Sync fixed function OpenGL state here!");
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index d8a43cc94..b6b426f34 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -89,7 +89,18 @@ OpenGLState::OpenGLState() {
89 point.size = 1; 89 point.size = 1;
90} 90}
91 91
92void OpenGLState::Apply() const { 92void OpenGLState::ApplyDefaultState() {
93 glDisable(GL_FRAMEBUFFER_SRGB);
94 glDisable(GL_CULL_FACE);
95 glDisable(GL_DEPTH_TEST);
96 glDisable(GL_PRIMITIVE_RESTART);
97 glDisable(GL_STENCIL_TEST);
98 glEnable(GL_BLEND);
99 glDisable(GL_COLOR_LOGIC_OP);
100 glDisable(GL_SCISSOR_TEST);
101}
102
103void OpenGLState::ApplySRgb() const {
93 // sRGB 104 // sRGB
94 if (framebuffer_srgb.enabled != cur_state.framebuffer_srgb.enabled) { 105 if (framebuffer_srgb.enabled != cur_state.framebuffer_srgb.enabled) {
95 if (framebuffer_srgb.enabled) { 106 if (framebuffer_srgb.enabled) {
@@ -100,96 +111,122 @@ void OpenGLState::Apply() const {
100 glDisable(GL_FRAMEBUFFER_SRGB); 111 glDisable(GL_FRAMEBUFFER_SRGB);
101 } 112 }
102 } 113 }
114}
115
116void OpenGLState::ApplyCulling() const {
103 // Culling 117 // Culling
104 if (cull.enabled != cur_state.cull.enabled) { 118 const bool cull_changed = cull.enabled != cur_state.cull.enabled;
119 if (cull_changed) {
105 if (cull.enabled) { 120 if (cull.enabled) {
106 glEnable(GL_CULL_FACE); 121 glEnable(GL_CULL_FACE);
107 } else { 122 } else {
108 glDisable(GL_CULL_FACE); 123 glDisable(GL_CULL_FACE);
109 } 124 }
110 } 125 }
126 if (cull.enabled) {
127 if (cull_changed || cull.mode != cur_state.cull.mode) {
128 glCullFace(cull.mode);
129 }
111 130
112 if (cull.mode != cur_state.cull.mode) { 131 if (cull_changed || cull.front_face != cur_state.cull.front_face) {
113 glCullFace(cull.mode); 132 glFrontFace(cull.front_face);
114 } 133 }
115
116 if (cull.front_face != cur_state.cull.front_face) {
117 glFrontFace(cull.front_face);
118 } 134 }
135}
119 136
137void OpenGLState::ApplyDepth() const {
120 // Depth test 138 // Depth test
121 if (depth.test_enabled != cur_state.depth.test_enabled) { 139 const bool depth_test_changed = depth.test_enabled != cur_state.depth.test_enabled;
140 if (depth_test_changed) {
122 if (depth.test_enabled) { 141 if (depth.test_enabled) {
123 glEnable(GL_DEPTH_TEST); 142 glEnable(GL_DEPTH_TEST);
124 } else { 143 } else {
125 glDisable(GL_DEPTH_TEST); 144 glDisable(GL_DEPTH_TEST);
126 } 145 }
127 } 146 }
128 147 if (depth.test_enabled &&
129 if (depth.test_func != cur_state.depth.test_func) { 148 (depth_test_changed || depth.test_func != cur_state.depth.test_func)) {
130 glDepthFunc(depth.test_func); 149 glDepthFunc(depth.test_func);
131 } 150 }
132
133 // Depth mask 151 // Depth mask
134 if (depth.write_mask != cur_state.depth.write_mask) { 152 if (depth.write_mask != cur_state.depth.write_mask) {
135 glDepthMask(depth.write_mask); 153 glDepthMask(depth.write_mask);
136 } 154 }
137
138 // Depth range 155 // Depth range
139 if (depth.depth_range_near != cur_state.depth.depth_range_near || 156 if (depth.depth_range_near != cur_state.depth.depth_range_near ||
140 depth.depth_range_far != cur_state.depth.depth_range_far) { 157 depth.depth_range_far != cur_state.depth.depth_range_far) {
141 glDepthRange(depth.depth_range_near, depth.depth_range_far); 158 glDepthRange(depth.depth_range_near, depth.depth_range_far);
142 } 159 }
160}
143 161
144 // Primitive restart 162void OpenGLState::ApplyPrimitiveRestart() const {
145 if (primitive_restart.enabled != cur_state.primitive_restart.enabled) { 163 const bool primitive_restart_changed =
164 primitive_restart.enabled != cur_state.primitive_restart.enabled;
165 if (primitive_restart_changed) {
146 if (primitive_restart.enabled) { 166 if (primitive_restart.enabled) {
147 glEnable(GL_PRIMITIVE_RESTART); 167 glEnable(GL_PRIMITIVE_RESTART);
148 } else { 168 } else {
149 glDisable(GL_PRIMITIVE_RESTART); 169 glDisable(GL_PRIMITIVE_RESTART);
150 } 170 }
151 } 171 }
152 if (primitive_restart.index != cur_state.primitive_restart.index) { 172 if (primitive_restart_changed ||
173 (primitive_restart.enabled &&
174 primitive_restart.index != cur_state.primitive_restart.index)) {
153 glPrimitiveRestartIndex(primitive_restart.index); 175 glPrimitiveRestartIndex(primitive_restart.index);
154 } 176 }
177}
155 178
156 // Color mask 179void OpenGLState::ApplyStencilTest() const {
157 if (color_mask.red_enabled != cur_state.color_mask.red_enabled || 180 const bool stencil_test_changed = stencil.test_enabled != cur_state.stencil.test_enabled;
158 color_mask.green_enabled != cur_state.color_mask.green_enabled || 181 if (stencil_test_changed) {
159 color_mask.blue_enabled != cur_state.color_mask.blue_enabled ||
160 color_mask.alpha_enabled != cur_state.color_mask.alpha_enabled) {
161 glColorMask(color_mask.red_enabled, color_mask.green_enabled, color_mask.blue_enabled,
162 color_mask.alpha_enabled);
163 }
164
165 // Stencil test
166 if (stencil.test_enabled != cur_state.stencil.test_enabled) {
167 if (stencil.test_enabled) { 182 if (stencil.test_enabled) {
168 glEnable(GL_STENCIL_TEST); 183 glEnable(GL_STENCIL_TEST);
169 } else { 184 } else {
170 glDisable(GL_STENCIL_TEST); 185 glDisable(GL_STENCIL_TEST);
171 } 186 }
172 } 187 }
173 auto config_stencil = [](GLenum face, const auto& config, const auto& prev_config) { 188 if (stencil.test_enabled) {
174 if (config.test_func != prev_config.test_func || config.test_ref != prev_config.test_ref || 189 auto config_stencil = [stencil_test_changed](GLenum face, const auto& config,
175 config.test_mask != prev_config.test_mask) { 190 const auto& prev_config) {
176 glStencilFuncSeparate(face, config.test_func, config.test_ref, config.test_mask); 191 if (stencil_test_changed || config.test_func != prev_config.test_func ||
177 } 192 config.test_ref != prev_config.test_ref ||
178 if (config.action_depth_fail != prev_config.action_depth_fail || 193 config.test_mask != prev_config.test_mask) {
179 config.action_depth_pass != prev_config.action_depth_pass || 194 glStencilFuncSeparate(face, config.test_func, config.test_ref, config.test_mask);
180 config.action_stencil_fail != prev_config.action_stencil_fail) { 195 }
181 glStencilOpSeparate(face, config.action_stencil_fail, config.action_depth_fail, 196 if (stencil_test_changed || config.action_depth_fail != prev_config.action_depth_fail ||
182 config.action_depth_pass); 197 config.action_depth_pass != prev_config.action_depth_pass ||
183 } 198 config.action_stencil_fail != prev_config.action_stencil_fail) {
184 if (config.write_mask != prev_config.write_mask) { 199 glStencilOpSeparate(face, config.action_stencil_fail, config.action_depth_fail,
185 glStencilMaskSeparate(face, config.write_mask); 200 config.action_depth_pass);
201 }
202 if (config.write_mask != prev_config.write_mask) {
203 glStencilMaskSeparate(face, config.write_mask);
204 }
205 };
206 config_stencil(GL_FRONT, stencil.front, cur_state.stencil.front);
207 config_stencil(GL_BACK, stencil.back, cur_state.stencil.back);
208 }
209}
210
211void OpenGLState::ApplyScissorTest() const {
212 const bool scissor_changed = scissor.enabled != cur_state.scissor.enabled;
213 if (scissor_changed) {
214 if (scissor.enabled) {
215 glEnable(GL_SCISSOR_TEST);
216 } else {
217 glDisable(GL_SCISSOR_TEST);
186 } 218 }
187 }; 219 }
188 config_stencil(GL_FRONT, stencil.front, cur_state.stencil.front); 220 if (scissor_changed || scissor_changed || scissor.x != cur_state.scissor.x ||
189 config_stencil(GL_BACK, stencil.back, cur_state.stencil.back); 221 scissor.y != cur_state.scissor.y || scissor.width != cur_state.scissor.width ||
222 scissor.height != cur_state.scissor.height) {
223 glScissor(scissor.x, scissor.y, scissor.width, scissor.height);
224 }
225}
190 226
191 // Blending 227void OpenGLState::ApplyBlending() const {
192 if (blend.enabled != cur_state.blend.enabled) { 228 const bool blend_changed = blend.enabled != cur_state.blend.enabled;
229 if (blend_changed) {
193 if (blend.enabled) { 230 if (blend.enabled) {
194 ASSERT(!logic_op.enabled); 231 ASSERT(!logic_op.enabled);
195 glEnable(GL_BLEND); 232 glEnable(GL_BLEND);
@@ -197,29 +234,32 @@ void OpenGLState::Apply() const {
197 glDisable(GL_BLEND); 234 glDisable(GL_BLEND);
198 } 235 }
199 } 236 }
237 if (blend.enabled) {
238 if (blend_changed || blend.color.red != cur_state.blend.color.red ||
239 blend.color.green != cur_state.blend.color.green ||
240 blend.color.blue != cur_state.blend.color.blue ||
241 blend.color.alpha != cur_state.blend.color.alpha) {
242 glBlendColor(blend.color.red, blend.color.green, blend.color.blue, blend.color.alpha);
243 }
200 244
201 if (blend.color.red != cur_state.blend.color.red || 245 if (blend_changed || blend.src_rgb_func != cur_state.blend.src_rgb_func ||
202 blend.color.green != cur_state.blend.color.green || 246 blend.dst_rgb_func != cur_state.blend.dst_rgb_func ||
203 blend.color.blue != cur_state.blend.color.blue || 247 blend.src_a_func != cur_state.blend.src_a_func ||
204 blend.color.alpha != cur_state.blend.color.alpha) { 248 blend.dst_a_func != cur_state.blend.dst_a_func) {
205 glBlendColor(blend.color.red, blend.color.green, blend.color.blue, blend.color.alpha); 249 glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func,
206 } 250 blend.dst_a_func);
207 251 }
208 if (blend.src_rgb_func != cur_state.blend.src_rgb_func ||
209 blend.dst_rgb_func != cur_state.blend.dst_rgb_func ||
210 blend.src_a_func != cur_state.blend.src_a_func ||
211 blend.dst_a_func != cur_state.blend.dst_a_func) {
212 glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func,
213 blend.dst_a_func);
214 }
215 252
216 if (blend.rgb_equation != cur_state.blend.rgb_equation || 253 if (blend_changed || blend.rgb_equation != cur_state.blend.rgb_equation ||
217 blend.a_equation != cur_state.blend.a_equation) { 254 blend.a_equation != cur_state.blend.a_equation) {
218 glBlendEquationSeparate(blend.rgb_equation, blend.a_equation); 255 glBlendEquationSeparate(blend.rgb_equation, blend.a_equation);
256 }
219 } 257 }
258}
220 259
221 // Logic Operation 260void OpenGLState::ApplyLogicOp() const {
222 if (logic_op.enabled != cur_state.logic_op.enabled) { 261 const bool logic_op_changed = logic_op.enabled != cur_state.logic_op.enabled;
262 if (logic_op_changed) {
223 if (logic_op.enabled) { 263 if (logic_op.enabled) {
224 ASSERT(!blend.enabled); 264 ASSERT(!blend.enabled);
225 glEnable(GL_COLOR_LOGIC_OP); 265 glEnable(GL_COLOR_LOGIC_OP);
@@ -228,11 +268,13 @@ void OpenGLState::Apply() const {
228 } 268 }
229 } 269 }
230 270
231 if (logic_op.operation != cur_state.logic_op.operation) { 271 if (logic_op.enabled &&
272 (logic_op_changed || logic_op.operation != cur_state.logic_op.operation)) {
232 glLogicOp(logic_op.operation); 273 glLogicOp(logic_op.operation);
233 } 274 }
275}
234 276
235 // Textures 277void OpenGLState::ApplyTextures() const {
236 for (std::size_t i = 0; i < std::size(texture_units); ++i) { 278 for (std::size_t i = 0; i < std::size(texture_units); ++i) {
237 const auto& texture_unit = texture_units[i]; 279 const auto& texture_unit = texture_units[i];
238 const auto& cur_state_texture_unit = cur_state.texture_units[i]; 280 const auto& cur_state_texture_unit = cur_state.texture_units[i];
@@ -251,28 +293,29 @@ void OpenGLState::Apply() const {
251 glTexParameteriv(texture_unit.target, GL_TEXTURE_SWIZZLE_RGBA, mask.data()); 293 glTexParameteriv(texture_unit.target, GL_TEXTURE_SWIZZLE_RGBA, mask.data());
252 } 294 }
253 } 295 }
296}
254 297
255 // Samplers 298void OpenGLState::ApplySamplers() const {
256 { 299 bool has_delta{};
257 bool has_delta{}; 300 std::size_t first{}, last{};
258 std::size_t first{}, last{}; 301 std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers;
259 std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers; 302 for (std::size_t i = 0; i < std::size(samplers); ++i) {
260 for (std::size_t i = 0; i < std::size(samplers); ++i) { 303 samplers[i] = texture_units[i].sampler;
261 samplers[i] = texture_units[i].sampler; 304 if (samplers[i] != cur_state.texture_units[i].sampler) {
262 if (samplers[i] != cur_state.texture_units[i].sampler) { 305 if (!has_delta) {
263 if (!has_delta) { 306 first = i;
264 first = i; 307 has_delta = true;
265 has_delta = true;
266 }
267 last = i;
268 } 308 }
269 } 309 last = i;
270 if (has_delta) {
271 glBindSamplers(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1),
272 samplers.data());
273 } 310 }
274 } 311 }
312 if (has_delta) {
313 glBindSamplers(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1),
314 samplers.data());
315 }
316}
275 317
318void OpenGLState::Apply() const {
276 // Framebuffer 319 // Framebuffer
277 if (draw.read_framebuffer != cur_state.draw.read_framebuffer) { 320 if (draw.read_framebuffer != cur_state.draw.read_framebuffer) {
278 glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer); 321 glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer);
@@ -305,27 +348,12 @@ void OpenGLState::Apply() const {
305 if (draw.program_pipeline != cur_state.draw.program_pipeline) { 348 if (draw.program_pipeline != cur_state.draw.program_pipeline) {
306 glBindProgramPipeline(draw.program_pipeline); 349 glBindProgramPipeline(draw.program_pipeline);
307 } 350 }
308 351 // Viewport
309 // Scissor test
310 if (scissor.enabled != cur_state.scissor.enabled) {
311 if (scissor.enabled) {
312 glEnable(GL_SCISSOR_TEST);
313 } else {
314 glDisable(GL_SCISSOR_TEST);
315 }
316 }
317
318 if (scissor.x != cur_state.scissor.x || scissor.y != cur_state.scissor.y ||
319 scissor.width != cur_state.scissor.width || scissor.height != cur_state.scissor.height) {
320 glScissor(scissor.x, scissor.y, scissor.width, scissor.height);
321 }
322
323 if (viewport.x != cur_state.viewport.x || viewport.y != cur_state.viewport.y || 352 if (viewport.x != cur_state.viewport.x || viewport.y != cur_state.viewport.y ||
324 viewport.width != cur_state.viewport.width || 353 viewport.width != cur_state.viewport.width ||
325 viewport.height != cur_state.viewport.height) { 354 viewport.height != cur_state.viewport.height) {
326 glViewport(viewport.x, viewport.y, viewport.width, viewport.height); 355 glViewport(viewport.x, viewport.y, viewport.width, viewport.height);
327 } 356 }
328
329 // Clip distance 357 // Clip distance
330 for (std::size_t i = 0; i < clip_distance.size(); ++i) { 358 for (std::size_t i = 0; i < clip_distance.size(); ++i) {
331 if (clip_distance[i] != cur_state.clip_distance[i]) { 359 if (clip_distance[i] != cur_state.clip_distance[i]) {
@@ -336,12 +364,28 @@ void OpenGLState::Apply() const {
336 } 364 }
337 } 365 }
338 } 366 }
339 367 // Color mask
368 if (color_mask.red_enabled != cur_state.color_mask.red_enabled ||
369 color_mask.green_enabled != cur_state.color_mask.green_enabled ||
370 color_mask.blue_enabled != cur_state.color_mask.blue_enabled ||
371 color_mask.alpha_enabled != cur_state.color_mask.alpha_enabled) {
372 glColorMask(color_mask.red_enabled, color_mask.green_enabled, color_mask.blue_enabled,
373 color_mask.alpha_enabled);
374 }
340 // Point 375 // Point
341 if (point.size != cur_state.point.size) { 376 if (point.size != cur_state.point.size) {
342 glPointSize(point.size); 377 glPointSize(point.size);
343 } 378 }
344 379 ApplyScissorTest();
380 ApplyStencilTest();
381 ApplySRgb();
382 ApplyCulling();
383 ApplyDepth();
384 ApplyPrimitiveRestart();
385 ApplyBlending();
386 ApplyLogicOp();
387 ApplyTextures();
388 ApplySamplers();
345 cur_state = *this; 389 cur_state = *this;
346} 390}
347 391
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 9e2c573b5..fe648aff6 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -173,7 +173,8 @@ public:
173 } 173 }
174 /// Apply this state as the current OpenGL state 174 /// Apply this state as the current OpenGL state
175 void Apply() const; 175 void Apply() const;
176 176 /// Set the initial OpenGL state
177 static void ApplyDefaultState();
177 /// Resets any references to the given resource 178 /// Resets any references to the given resource
178 OpenGLState& UnbindTexture(GLuint handle); 179 OpenGLState& UnbindTexture(GLuint handle);
179 OpenGLState& ResetSampler(GLuint handle); 180 OpenGLState& ResetSampler(GLuint handle);
@@ -188,6 +189,16 @@ private:
188 // Workaround for sRGB problems caused by 189 // Workaround for sRGB problems caused by
189 // QT not supporting srgb output 190 // QT not supporting srgb output
190 static bool s_rgb_used; 191 static bool s_rgb_used;
192 void ApplySRgb() const;
193 void ApplyCulling() const;
194 void ApplyDepth() const;
195 void ApplyPrimitiveRestart() const;
196 void ApplyStencilTest() const;
197 void ApplyScissorTest() const;
198 void ApplyBlending() const;
199 void ApplyLogicOp() const;
200 void ApplyTextures() const;
201 void ApplySamplers() const;
191}; 202};
192 203
193} // namespace OpenGL 204} // namespace OpenGL