diff options
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 54 |
1 files changed, 42 insertions, 12 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 516e1b50f..954ec10ca 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "common/logging/log.h" | 14 | #include "common/logging/log.h" |
| 15 | #include "common/math_util.h" | 15 | #include "common/math_util.h" |
| 16 | #include "common/microprofile.h" | 16 | #include "common/microprofile.h" |
| 17 | #include "common/scope_exit.h" | ||
| 17 | #include "core/core.h" | 18 | #include "core/core.h" |
| 18 | #include "core/frontend/emu_window.h" | 19 | #include "core/frontend/emu_window.h" |
| 19 | #include "core/hle/kernel/process.h" | 20 | #include "core/hle/kernel/process.h" |
| @@ -364,41 +365,70 @@ std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers(bool using_c | |||
| 364 | } | 365 | } |
| 365 | 366 | ||
| 366 | void RasterizerOpenGL::Clear() { | 367 | void RasterizerOpenGL::Clear() { |
| 367 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; | 368 | const auto prev_state{state}; |
| 369 | SCOPE_EXIT({ prev_state.Apply(); }); | ||
| 368 | 370 | ||
| 371 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; | ||
| 369 | bool use_color_fb = false; | 372 | bool use_color_fb = false; |
| 370 | bool use_depth_fb = false; | 373 | bool use_depth_fb = false; |
| 371 | 374 | ||
| 372 | GLbitfield clear_mask = 0; | 375 | OpenGLState clear_state; |
| 373 | if (regs.clear_buffers.R && regs.clear_buffers.G && regs.clear_buffers.B && | 376 | clear_state.draw.draw_framebuffer = state.draw.draw_framebuffer; |
| 377 | clear_state.color_mask.red_enabled = regs.clear_buffers.R ? GL_TRUE : GL_FALSE; | ||
| 378 | clear_state.color_mask.green_enabled = regs.clear_buffers.G ? GL_TRUE : GL_FALSE; | ||
| 379 | clear_state.color_mask.blue_enabled = regs.clear_buffers.B ? GL_TRUE : GL_FALSE; | ||
| 380 | clear_state.color_mask.alpha_enabled = regs.clear_buffers.A ? GL_TRUE : GL_FALSE; | ||
| 381 | |||
| 382 | GLbitfield clear_mask{}; | ||
| 383 | if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B || | ||
| 374 | regs.clear_buffers.A) { | 384 | regs.clear_buffers.A) { |
| 375 | clear_mask |= GL_COLOR_BUFFER_BIT; | 385 | if (regs.clear_buffers.RT == 0) { |
| 376 | use_color_fb = true; | 386 | // We only support clearing the first color attachment for now |
| 387 | clear_mask |= GL_COLOR_BUFFER_BIT; | ||
| 388 | use_color_fb = true; | ||
| 389 | } else { | ||
| 390 | // TODO(subv): Add support for the other color attachments | ||
| 391 | LOG_CRITICAL(HW_GPU, "Clear unimplemented for RT {}", regs.clear_buffers.RT); | ||
| 392 | } | ||
| 377 | } | 393 | } |
| 378 | if (regs.clear_buffers.Z) { | 394 | if (regs.clear_buffers.Z) { |
| 395 | ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear Z but buffer is not enabled!"); | ||
| 396 | use_depth_fb = true; | ||
| 379 | clear_mask |= GL_DEPTH_BUFFER_BIT; | 397 | clear_mask |= GL_DEPTH_BUFFER_BIT; |
| 380 | use_depth_fb = regs.zeta_enable != 0; | ||
| 381 | 398 | ||
| 382 | // Always enable the depth write when clearing the depth buffer. The depth write mask is | 399 | // Always enable the depth write when clearing the depth buffer. The depth write mask is |
| 383 | // ignored when clearing the buffer in the Switch, but OpenGL obeys it so we set it to true. | 400 | // ignored when clearing the buffer in the Switch, but OpenGL obeys it so we set it to true. |
| 384 | state.depth.test_enabled = true; | 401 | clear_state.depth.test_enabled = true; |
| 385 | state.depth.write_mask = GL_TRUE; | 402 | clear_state.depth.test_func = GL_ALWAYS; |
| 386 | state.depth.test_func = GL_ALWAYS; | 403 | } |
| 387 | state.Apply(); | 404 | if (regs.clear_buffers.S) { |
| 405 | ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear stencil but buffer is not enabled!"); | ||
| 406 | use_depth_fb = true; | ||
| 407 | clear_mask |= GL_STENCIL_BUFFER_BIT; | ||
| 408 | clear_state.stencil.test_enabled = true; | ||
| 388 | } | 409 | } |
| 389 | 410 | ||
| 390 | if (clear_mask == 0) | 411 | if (!use_color_fb && !use_depth_fb) { |
| 412 | // No color surface nor depth/stencil surface are enabled | ||
| 391 | return; | 413 | return; |
| 414 | } | ||
| 415 | |||
| 416 | if (clear_mask == 0) { | ||
| 417 | // No clear mask is enabled | ||
| 418 | return; | ||
| 419 | } | ||
| 392 | 420 | ||
| 393 | ScopeAcquireGLContext acquire_context{emu_window}; | 421 | ScopeAcquireGLContext acquire_context{emu_window}; |
| 394 | 422 | ||
| 395 | auto [dirty_color_surface, dirty_depth_surface] = | 423 | auto [dirty_color_surface, dirty_depth_surface] = |
| 396 | ConfigureFramebuffers(use_color_fb, use_depth_fb, false); | 424 | ConfigureFramebuffers(use_color_fb, use_depth_fb, false); |
| 397 | 425 | ||
| 398 | // TODO(Subv): Support clearing only partial colors. | 426 | clear_state.Apply(); |
| 427 | |||
| 399 | glClearColor(regs.clear_color[0], regs.clear_color[1], regs.clear_color[2], | 428 | glClearColor(regs.clear_color[0], regs.clear_color[1], regs.clear_color[2], |
| 400 | regs.clear_color[3]); | 429 | regs.clear_color[3]); |
| 401 | glClearDepth(regs.clear_depth); | 430 | glClearDepth(regs.clear_depth); |
| 431 | glClearStencil(regs.clear_stencil); | ||
| 402 | 432 | ||
| 403 | glClear(clear_mask); | 433 | glClear(clear_mask); |
| 404 | 434 | ||