diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/citra_qt/CMakeLists.txt | 8 | ||||
| -rw-r--r-- | src/common/math_util.h | 2 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/arm_regformat.h | 2 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/vfp/vfp.cpp | 4 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/vfp/vfp.h | 1 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/vfp/vfpinstr.cpp | 18 | ||||
| -rw-r--r-- | src/video_core/pica.h | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 154 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 36 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 6 |
11 files changed, 163 insertions, 81 deletions
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index c05779380..c2d1ad240 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt | |||
| @@ -91,10 +91,10 @@ if (Qt5_FOUND AND MSVC) | |||
| 91 | set(PLATFORMS ${DLL_DEST}platforms/) | 91 | set(PLATFORMS ${DLL_DEST}platforms/) |
| 92 | 92 | ||
| 93 | # windows commandline expects the / to be \ so switch them | 93 | # windows commandline expects the / to be \ so switch them |
| 94 | string(REPLACE "/" "\\" Qt5_DLL_DIR ${Qt5_DLL_DIR}) | 94 | string(REPLACE "/" "\\\\" Qt5_DLL_DIR ${Qt5_DLL_DIR}) |
| 95 | string(REPLACE "/" "\\" Qt5_PLATFORMS_DIR ${Qt5_PLATFORMS_DIR}) | 95 | string(REPLACE "/" "\\\\" Qt5_PLATFORMS_DIR ${Qt5_PLATFORMS_DIR}) |
| 96 | string(REPLACE "/" "\\" DLL_DEST ${DLL_DEST}) | 96 | string(REPLACE "/" "\\\\" DLL_DEST ${DLL_DEST}) |
| 97 | string(REPLACE "/" "\\" PLATFORMS ${PLATFORMS}) | 97 | string(REPLACE "/" "\\\\" PLATFORMS ${PLATFORMS}) |
| 98 | 98 | ||
| 99 | # /NJH /NJS /NDL /NFL /NC /NS /NP - Silence any output | 99 | # /NJH /NJS /NDL /NFL /NC /NS /NP - Silence any output |
| 100 | # cmake adds an extra check for command success which doesn't work too well with robocopy | 100 | # cmake adds an extra check for command success which doesn't work too well with robocopy |
diff --git a/src/common/math_util.h b/src/common/math_util.h index 4b0910741..d44b06e74 100644 --- a/src/common/math_util.h +++ b/src/common/math_util.h | |||
| @@ -12,7 +12,7 @@ namespace MathUtil | |||
| 12 | { | 12 | { |
| 13 | 13 | ||
| 14 | inline bool IntervalsIntersect(unsigned start0, unsigned length0, unsigned start1, unsigned length1) { | 14 | inline bool IntervalsIntersect(unsigned start0, unsigned length0, unsigned start1, unsigned length1) { |
| 15 | return (std::max(start0, start1) <= std::min(start0 + length0, start1 + length1)); | 15 | return (std::max(start0, start1) < std::min(start0 + length0, start1 + length1)); |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | template<typename T> | 18 | template<typename T> |
diff --git a/src/core/arm/skyeye_common/arm_regformat.h b/src/core/arm/skyeye_common/arm_regformat.h index 6c89774eb..a92effbb4 100644 --- a/src/core/arm/skyeye_common/arm_regformat.h +++ b/src/core/arm/skyeye_common/arm_regformat.h | |||
| @@ -59,6 +59,8 @@ enum { | |||
| 59 | VFP_FPSID, | 59 | VFP_FPSID, |
| 60 | VFP_FPSCR, | 60 | VFP_FPSCR, |
| 61 | VFP_FPEXC, | 61 | VFP_FPEXC, |
| 62 | VFP_MVFR0, | ||
| 63 | VFP_MVFR1, | ||
| 62 | 64 | ||
| 63 | // Not an actual register. | 65 | // Not an actual register. |
| 64 | // All VFP system registers should be defined above this. | 66 | // All VFP system registers should be defined above this. |
diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp index b88d47750..571d6c2f2 100644 --- a/src/core/arm/skyeye_common/vfp/vfp.cpp +++ b/src/core/arm/skyeye_common/vfp/vfp.cpp | |||
| @@ -33,6 +33,10 @@ unsigned VFPInit(ARMul_State* state) | |||
| 33 | state->VFP[VFP_FPEXC] = 0; | 33 | state->VFP[VFP_FPEXC] = 0; |
| 34 | state->VFP[VFP_FPSCR] = 0; | 34 | state->VFP[VFP_FPSCR] = 0; |
| 35 | 35 | ||
| 36 | // ARM11 MPCore feature register values. | ||
| 37 | state->VFP[VFP_MVFR0] = 0x11111111; | ||
| 38 | state->VFP[VFP_MVFR1] = 0; | ||
| 39 | |||
| 36 | return 0; | 40 | return 0; |
| 37 | } | 41 | } |
| 38 | 42 | ||
diff --git a/src/core/arm/skyeye_common/vfp/vfp.h b/src/core/arm/skyeye_common/vfp/vfp.h index 727350f14..acefae9bb 100644 --- a/src/core/arm/skyeye_common/vfp/vfp.h +++ b/src/core/arm/skyeye_common/vfp/vfp.h | |||
| @@ -22,7 +22,6 @@ | |||
| 22 | 22 | ||
| 23 | #include "core/arm/skyeye_common/vfp/vfp_helper.h" /* for references to cdp SoftFloat functions */ | 23 | #include "core/arm/skyeye_common/vfp/vfp_helper.h" /* for references to cdp SoftFloat functions */ |
| 24 | 24 | ||
| 25 | #define VFP_DEBUG_UNIMPLEMENTED(x) LOG_ERROR(Core_ARM11, "in func %s, " #x " unimplemented\n", __FUNCTION__); exit(-1); | ||
| 26 | #define VFP_DEBUG_UNTESTED(x) LOG_TRACE(Core_ARM11, "in func %s, " #x " untested\n", __FUNCTION__); | 25 | #define VFP_DEBUG_UNTESTED(x) LOG_TRACE(Core_ARM11, "in func %s, " #x " untested\n", __FUNCTION__); |
| 27 | #define CHECK_VFP_ENABLED | 26 | #define CHECK_VFP_ENABLED |
| 28 | #define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_FPSCR]); | 27 | #define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_FPSCR]); |
diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp index 3ed918a93..67fe63aa4 100644 --- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp | |||
| @@ -1068,10 +1068,12 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index) | |||
| 1068 | #ifdef VFP_INTERPRETER_IMPL | 1068 | #ifdef VFP_INTERPRETER_IMPL |
| 1069 | VMOVBRC_INST: | 1069 | VMOVBRC_INST: |
| 1070 | { | 1070 | { |
| 1071 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { | 1071 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 1072 | CHECK_VFP_ENABLED; | 1072 | CHECK_VFP_ENABLED; |
| 1073 | 1073 | ||
| 1074 | VFP_DEBUG_UNIMPLEMENTED(VMOVBRC); | 1074 | vmovbrc_inst* const inst_cream = (vmovbrc_inst*)inst_base->component; |
| 1075 | |||
| 1076 | cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index] = cpu->Reg[inst_cream->t]; | ||
| 1075 | } | 1077 | } |
| 1076 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1078 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| 1077 | INC_PC(sizeof(vmovbrc_inst)); | 1079 | INC_PC(sizeof(vmovbrc_inst)); |
| @@ -1139,12 +1141,10 @@ VMRS_INST: | |||
| 1139 | cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_FPSID]; | 1141 | cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_FPSID]; |
| 1140 | break; | 1142 | break; |
| 1141 | case 6: | 1143 | case 6: |
| 1142 | /* MVFR1, VFPv3 only ? */ | 1144 | cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_MVFR1]; |
| 1143 | LOG_TRACE(Core_ARM11, "\tr%d <= MVFR1 unimplemented\n", inst_cream->Rt); | ||
| 1144 | break; | 1145 | break; |
| 1145 | case 7: | 1146 | case 7: |
| 1146 | /* MVFR0, VFPv3 only? */ | 1147 | cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_MVFR0]; |
| 1147 | LOG_TRACE(Core_ARM11, "\tr%d <= MVFR0 unimplemented\n", inst_cream->Rt); | ||
| 1148 | break; | 1148 | break; |
| 1149 | case 8: | 1149 | case 8: |
| 1150 | cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_FPEXC]; | 1150 | cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_FPEXC]; |
| @@ -1195,10 +1195,12 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index) | |||
| 1195 | #ifdef VFP_INTERPRETER_IMPL | 1195 | #ifdef VFP_INTERPRETER_IMPL |
| 1196 | VMOVBCR_INST: | 1196 | VMOVBCR_INST: |
| 1197 | { | 1197 | { |
| 1198 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { | 1198 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 1199 | CHECK_VFP_ENABLED; | 1199 | CHECK_VFP_ENABLED; |
| 1200 | 1200 | ||
| 1201 | VFP_DEBUG_UNIMPLEMENTED(VMOVBCR); | 1201 | vmovbcr_inst* const inst_cream = (vmovbcr_inst*) inst_base->component; |
| 1202 | |||
| 1203 | cpu->Reg[inst_cream->t] = cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index]; | ||
| 1202 | } | 1204 | } |
| 1203 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1205 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| 1204 | INC_PC(sizeof(vmovbcr_inst)); | 1206 | INC_PC(sizeof(vmovbcr_inst)); |
diff --git a/src/video_core/pica.h b/src/video_core/pica.h index 684ec9818..9628a7589 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h | |||
| @@ -372,9 +372,9 @@ struct Regs { | |||
| 372 | INSERT_PADDING_WORDS(0x2); | 372 | INSERT_PADDING_WORDS(0x2); |
| 373 | 373 | ||
| 374 | const std::array<Regs::TevStageConfig,6> GetTevStages() const { | 374 | const std::array<Regs::TevStageConfig,6> GetTevStages() const { |
| 375 | return { tev_stage0, tev_stage1, | 375 | return {{ tev_stage0, tev_stage1, |
| 376 | tev_stage2, tev_stage3, | 376 | tev_stage2, tev_stage3, |
| 377 | tev_stage4, tev_stage5 }; | 377 | tev_stage4, tev_stage5 }}; |
| 378 | }; | 378 | }; |
| 379 | 379 | ||
| 380 | enum class BlendEquation : u32 { | 380 | enum class BlendEquation : u32 { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index d31c46cca..518f79331 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -94,14 +94,27 @@ void RasterizerOpenGL::InitObjects() { | |||
| 94 | // Create textures for OGL framebuffer that will be rendered to, initially 1x1 to succeed in framebuffer creation | 94 | // Create textures for OGL framebuffer that will be rendered to, initially 1x1 to succeed in framebuffer creation |
| 95 | fb_color_texture.texture.Create(); | 95 | fb_color_texture.texture.Create(); |
| 96 | ReconfigureColorTexture(fb_color_texture, Pica::Regs::ColorFormat::RGBA8, 1, 1); | 96 | ReconfigureColorTexture(fb_color_texture, Pica::Regs::ColorFormat::RGBA8, 1, 1); |
| 97 | |||
| 98 | state.texture_units[0].enabled_2d = true; | ||
| 99 | state.texture_units[0].texture_2d = fb_color_texture.texture.handle; | ||
| 100 | state.Apply(); | ||
| 101 | |||
| 97 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); | 102 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); |
| 98 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 103 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 99 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 104 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 100 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 105 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 101 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 106 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 102 | 107 | ||
| 108 | state.texture_units[0].texture_2d = 0; | ||
| 109 | state.Apply(); | ||
| 110 | |||
| 103 | fb_depth_texture.texture.Create(); | 111 | fb_depth_texture.texture.Create(); |
| 104 | ReconfigureDepthTexture(fb_depth_texture, Pica::Regs::DepthFormat::D16, 1, 1); | 112 | ReconfigureDepthTexture(fb_depth_texture, Pica::Regs::DepthFormat::D16, 1, 1); |
| 113 | |||
| 114 | state.texture_units[0].enabled_2d = true; | ||
| 115 | state.texture_units[0].texture_2d = fb_depth_texture.texture.handle; | ||
| 116 | state.Apply(); | ||
| 117 | |||
| 105 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); | 118 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); |
| 106 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 119 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 107 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 120 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| @@ -110,14 +123,13 @@ void RasterizerOpenGL::InitObjects() { | |||
| 110 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); | 123 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); |
| 111 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); | 124 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); |
| 112 | 125 | ||
| 126 | state.texture_units[0].texture_2d = 0; | ||
| 127 | state.Apply(); | ||
| 128 | |||
| 113 | // Configure OpenGL framebuffer | 129 | // Configure OpenGL framebuffer |
| 114 | framebuffer.Create(); | 130 | framebuffer.Create(); |
| 115 | 131 | ||
| 116 | state.draw.framebuffer = framebuffer.handle; | 132 | state.draw.framebuffer = framebuffer.handle; |
| 117 | |||
| 118 | // Unbind texture to allow binding to framebuffer | ||
| 119 | state.texture_units[0].enabled_2d = true; | ||
| 120 | state.texture_units[0].texture_2d = 0; | ||
| 121 | state.Apply(); | 133 | state.Apply(); |
| 122 | 134 | ||
| 123 | glActiveTexture(GL_TEXTURE0); | 135 | glActiveTexture(GL_TEXTURE0); |
| @@ -205,7 +217,19 @@ void RasterizerOpenGL::DrawTriangles() { | |||
| 205 | 217 | ||
| 206 | vertex_batch.clear(); | 218 | vertex_batch.clear(); |
| 207 | 219 | ||
| 208 | // TODO: Flush the resource cache at the current depth and color framebuffer addresses for render-to-texture | 220 | // Flush the resource cache at the current depth and color framebuffer addresses for render-to-texture |
| 221 | const auto& regs = Pica::g_state.regs; | ||
| 222 | |||
| 223 | PAddr cur_fb_color_addr = regs.framebuffer.GetColorBufferPhysicalAddress(); | ||
| 224 | u32 cur_fb_color_size = Pica::Regs::BytesPerColorPixel(regs.framebuffer.color_format) | ||
| 225 | * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight(); | ||
| 226 | |||
| 227 | PAddr cur_fb_depth_addr = regs.framebuffer.GetDepthBufferPhysicalAddress(); | ||
| 228 | u32 cur_fb_depth_size = Pica::Regs::BytesPerDepthPixel(regs.framebuffer.depth_format) | ||
| 229 | * regs.framebuffer.GetWidth() * regs.framebuffer.GetHeight(); | ||
| 230 | |||
| 231 | res_cache.NotifyFlush(cur_fb_color_addr, cur_fb_color_size); | ||
| 232 | res_cache.NotifyFlush(cur_fb_depth_addr, cur_fb_depth_size); | ||
| 209 | } | 233 | } |
| 210 | 234 | ||
| 211 | void RasterizerOpenGL::CommitFramebuffer() { | 235 | void RasterizerOpenGL::CommitFramebuffer() { |
| @@ -472,6 +496,9 @@ void RasterizerOpenGL::ReconfigureColorTexture(TextureInfo& texture, Pica::Regs: | |||
| 472 | glActiveTexture(GL_TEXTURE0); | 496 | glActiveTexture(GL_TEXTURE0); |
| 473 | glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0, | 497 | glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0, |
| 474 | texture.gl_format, texture.gl_type, nullptr); | 498 | texture.gl_format, texture.gl_type, nullptr); |
| 499 | |||
| 500 | state.texture_units[0].texture_2d = 0; | ||
| 501 | state.Apply(); | ||
| 475 | } | 502 | } |
| 476 | 503 | ||
| 477 | void RasterizerOpenGL::ReconfigureDepthTexture(DepthTextureInfo& texture, Pica::Regs::DepthFormat format, u32 width, u32 height) { | 504 | void RasterizerOpenGL::ReconfigureDepthTexture(DepthTextureInfo& texture, Pica::Regs::DepthFormat format, u32 width, u32 height) { |
| @@ -491,7 +518,7 @@ void RasterizerOpenGL::ReconfigureDepthTexture(DepthTextureInfo& texture, Pica:: | |||
| 491 | case Pica::Regs::DepthFormat::D24: | 518 | case Pica::Regs::DepthFormat::D24: |
| 492 | internal_format = GL_DEPTH_COMPONENT24; | 519 | internal_format = GL_DEPTH_COMPONENT24; |
| 493 | texture.gl_format = GL_DEPTH_COMPONENT; | 520 | texture.gl_format = GL_DEPTH_COMPONENT; |
| 494 | texture.gl_type = GL_UNSIGNED_INT_24_8; | 521 | texture.gl_type = GL_UNSIGNED_INT; |
| 495 | break; | 522 | break; |
| 496 | 523 | ||
| 497 | case Pica::Regs::DepthFormat::D24S8: | 524 | case Pica::Regs::DepthFormat::D24S8: |
| @@ -513,6 +540,9 @@ void RasterizerOpenGL::ReconfigureDepthTexture(DepthTextureInfo& texture, Pica:: | |||
| 513 | glActiveTexture(GL_TEXTURE0); | 540 | glActiveTexture(GL_TEXTURE0); |
| 514 | glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0, | 541 | glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0, |
| 515 | texture.gl_format, texture.gl_type, nullptr); | 542 | texture.gl_format, texture.gl_type, nullptr); |
| 543 | |||
| 544 | state.texture_units[0].texture_2d = 0; | ||
| 545 | state.Apply(); | ||
| 516 | } | 546 | } |
| 517 | 547 | ||
| 518 | void RasterizerOpenGL::SyncFramebuffer() { | 548 | void RasterizerOpenGL::SyncFramebuffer() { |
| @@ -652,6 +682,10 @@ void RasterizerOpenGL::SyncDepthTest() { | |||
| 652 | const auto& regs = Pica::g_state.regs; | 682 | const auto& regs = Pica::g_state.regs; |
| 653 | state.depth.test_enabled = (regs.output_merger.depth_test_enable == 1); | 683 | state.depth.test_enabled = (regs.output_merger.depth_test_enable == 1); |
| 654 | state.depth.test_func = PicaToGL::CompareFunc(regs.output_merger.depth_test_func); | 684 | state.depth.test_func = PicaToGL::CompareFunc(regs.output_merger.depth_test_func); |
| 685 | state.color_mask.red_enabled = regs.output_merger.red_enable; | ||
| 686 | state.color_mask.green_enabled = regs.output_merger.green_enable; | ||
| 687 | state.color_mask.blue_enabled = regs.output_merger.blue_enable; | ||
| 688 | state.color_mask.alpha_enabled = regs.output_merger.alpha_enable; | ||
| 655 | state.depth.write_mask = regs.output_merger.depth_write_enable ? GL_TRUE : GL_FALSE; | 689 | state.depth.write_mask = regs.output_merger.depth_write_enable ? GL_TRUE : GL_FALSE; |
| 656 | } | 690 | } |
| 657 | 691 | ||
| @@ -759,10 +793,10 @@ void RasterizerOpenGL::ReloadColorBuffer() { | |||
| 759 | for (int x = 0; x < fb_color_texture.width; ++x) { | 793 | for (int x = 0; x < fb_color_texture.width; ++x) { |
| 760 | const u32 coarse_y = y & ~7; | 794 | const u32 coarse_y = y & ~7; |
| 761 | u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_color_texture.width * bytes_per_pixel; | 795 | u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_color_texture.width * bytes_per_pixel; |
| 762 | u32 gl_px_idx = x * bytes_per_pixel + y * fb_color_texture.width * bytes_per_pixel; | 796 | u32 gl_pixel_index = (x + y * fb_color_texture.width) * bytes_per_pixel; |
| 763 | 797 | ||
| 764 | u8* pixel = color_buffer + dst_offset; | 798 | u8* pixel = color_buffer + dst_offset; |
| 765 | memcpy(&temp_fb_color_buffer[gl_px_idx], pixel, bytes_per_pixel); | 799 | memcpy(&temp_fb_color_buffer[gl_pixel_index], pixel, bytes_per_pixel); |
| 766 | } | 800 | } |
| 767 | } | 801 | } |
| 768 | 802 | ||
| @@ -773,6 +807,9 @@ void RasterizerOpenGL::ReloadColorBuffer() { | |||
| 773 | glActiveTexture(GL_TEXTURE0); | 807 | glActiveTexture(GL_TEXTURE0); |
| 774 | glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fb_color_texture.width, fb_color_texture.height, | 808 | glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fb_color_texture.width, fb_color_texture.height, |
| 775 | fb_color_texture.gl_format, fb_color_texture.gl_type, temp_fb_color_buffer.get()); | 809 | fb_color_texture.gl_format, fb_color_texture.gl_type, temp_fb_color_buffer.get()); |
| 810 | |||
| 811 | state.texture_units[0].texture_2d = 0; | ||
| 812 | state.Apply(); | ||
| 776 | } | 813 | } |
| 777 | 814 | ||
| 778 | void RasterizerOpenGL::ReloadDepthBuffer() { | 815 | void RasterizerOpenGL::ReloadDepthBuffer() { |
| @@ -790,29 +827,29 @@ void RasterizerOpenGL::ReloadDepthBuffer() { | |||
| 790 | 827 | ||
| 791 | std::unique_ptr<u8[]> temp_fb_depth_buffer(new u8[fb_depth_texture.width * fb_depth_texture.height * gl_bpp]); | 828 | std::unique_ptr<u8[]> temp_fb_depth_buffer(new u8[fb_depth_texture.width * fb_depth_texture.height * gl_bpp]); |
| 792 | 829 | ||
| 793 | for (int y = 0; y < fb_depth_texture.height; ++y) { | 830 | u8* temp_fb_depth_data = bytes_per_pixel == 3 ? (temp_fb_depth_buffer.get() + 1) : temp_fb_depth_buffer.get(); |
| 794 | for (int x = 0; x < fb_depth_texture.width; ++x) { | 831 | |
| 795 | const u32 coarse_y = y & ~7; | 832 | if (fb_depth_texture.format == Pica::Regs::DepthFormat::D24S8) { |
| 796 | u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel; | 833 | for (int y = 0; y < fb_depth_texture.height; ++y) { |
| 797 | u32 gl_px_idx = x + y * fb_depth_texture.width; | 834 | for (int x = 0; x < fb_depth_texture.width; ++x) { |
| 798 | 835 | const u32 coarse_y = y & ~7; | |
| 799 | switch (fb_depth_texture.format) { | 836 | u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel; |
| 800 | case Pica::Regs::DepthFormat::D16: | 837 | u32 gl_pixel_index = (x + y * fb_depth_texture.width); |
| 801 | ((u16*)temp_fb_depth_buffer.get())[gl_px_idx] = Color::DecodeD16(depth_buffer + dst_offset); | 838 | |
| 802 | break; | 839 | u8* pixel = depth_buffer + dst_offset; |
| 803 | case Pica::Regs::DepthFormat::D24: | 840 | u32 depth_stencil = *(u32*)pixel; |
| 804 | ((u32*)temp_fb_depth_buffer.get())[gl_px_idx] = Color::DecodeD24(depth_buffer + dst_offset); | 841 | ((u32*)temp_fb_depth_data)[gl_pixel_index] = (depth_stencil << 8) | (depth_stencil >> 24); |
| 805 | break; | ||
| 806 | case Pica::Regs::DepthFormat::D24S8: | ||
| 807 | { | ||
| 808 | Math::Vec2<u32> depth_stencil = Color::DecodeD24S8(depth_buffer + dst_offset); | ||
| 809 | ((u32*)temp_fb_depth_buffer.get())[gl_px_idx] = (depth_stencil.x << 8) | depth_stencil.y; | ||
| 810 | break; | ||
| 811 | } | 842 | } |
| 812 | default: | 843 | } |
| 813 | LOG_CRITICAL(Render_OpenGL, "Unknown memory framebuffer depth format %x", fb_depth_texture.format); | 844 | } else { |
| 814 | UNIMPLEMENTED(); | 845 | for (int y = 0; y < fb_depth_texture.height; ++y) { |
| 815 | break; | 846 | for (int x = 0; x < fb_depth_texture.width; ++x) { |
| 847 | const u32 coarse_y = y & ~7; | ||
| 848 | u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel; | ||
| 849 | u32 gl_pixel_index = (x + y * fb_depth_texture.width) * gl_bpp; | ||
| 850 | |||
| 851 | u8* pixel = depth_buffer + dst_offset; | ||
| 852 | memcpy(&temp_fb_depth_data[gl_pixel_index], pixel, bytes_per_pixel); | ||
| 816 | } | 853 | } |
| 817 | } | 854 | } |
| 818 | } | 855 | } |
| @@ -824,6 +861,9 @@ void RasterizerOpenGL::ReloadDepthBuffer() { | |||
| 824 | glActiveTexture(GL_TEXTURE0); | 861 | glActiveTexture(GL_TEXTURE0); |
| 825 | glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fb_depth_texture.width, fb_depth_texture.height, | 862 | glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fb_depth_texture.width, fb_depth_texture.height, |
| 826 | fb_depth_texture.gl_format, fb_depth_texture.gl_type, temp_fb_depth_buffer.get()); | 863 | fb_depth_texture.gl_format, fb_depth_texture.gl_type, temp_fb_depth_buffer.get()); |
| 864 | |||
| 865 | state.texture_units[0].texture_2d = 0; | ||
| 866 | state.Apply(); | ||
| 827 | } | 867 | } |
| 828 | 868 | ||
| 829 | void RasterizerOpenGL::CommitColorBuffer() { | 869 | void RasterizerOpenGL::CommitColorBuffer() { |
| @@ -842,15 +882,18 @@ void RasterizerOpenGL::CommitColorBuffer() { | |||
| 842 | glActiveTexture(GL_TEXTURE0); | 882 | glActiveTexture(GL_TEXTURE0); |
| 843 | glGetTexImage(GL_TEXTURE_2D, 0, fb_color_texture.gl_format, fb_color_texture.gl_type, temp_gl_color_buffer.get()); | 883 | glGetTexImage(GL_TEXTURE_2D, 0, fb_color_texture.gl_format, fb_color_texture.gl_type, temp_gl_color_buffer.get()); |
| 844 | 884 | ||
| 885 | state.texture_units[0].texture_2d = 0; | ||
| 886 | state.Apply(); | ||
| 887 | |||
| 845 | // Directly copy pixels. Internal OpenGL color formats are consistent so no conversion is necessary. | 888 | // Directly copy pixels. Internal OpenGL color formats are consistent so no conversion is necessary. |
| 846 | for (int y = 0; y < fb_color_texture.height; ++y) { | 889 | for (int y = 0; y < fb_color_texture.height; ++y) { |
| 847 | for (int x = 0; x < fb_color_texture.width; ++x) { | 890 | for (int x = 0; x < fb_color_texture.width; ++x) { |
| 848 | const u32 coarse_y = y & ~7; | 891 | const u32 coarse_y = y & ~7; |
| 849 | u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_color_texture.width * bytes_per_pixel; | 892 | u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_color_texture.width * bytes_per_pixel; |
| 850 | u32 gl_px_idx = x * bytes_per_pixel + y * fb_color_texture.width * bytes_per_pixel; | 893 | u32 gl_pixel_index = x * bytes_per_pixel + y * fb_color_texture.width * bytes_per_pixel; |
| 851 | 894 | ||
| 852 | u8* pixel = color_buffer + dst_offset; | 895 | u8* pixel = color_buffer + dst_offset; |
| 853 | memcpy(pixel, &temp_gl_color_buffer[gl_px_idx], bytes_per_pixel); | 896 | memcpy(pixel, &temp_gl_color_buffer[gl_pixel_index], bytes_per_pixel); |
| 854 | } | 897 | } |
| 855 | } | 898 | } |
| 856 | } | 899 | } |
| @@ -877,29 +920,32 @@ void RasterizerOpenGL::CommitDepthBuffer() { | |||
| 877 | glActiveTexture(GL_TEXTURE0); | 920 | glActiveTexture(GL_TEXTURE0); |
| 878 | glGetTexImage(GL_TEXTURE_2D, 0, fb_depth_texture.gl_format, fb_depth_texture.gl_type, temp_gl_depth_buffer.get()); | 921 | glGetTexImage(GL_TEXTURE_2D, 0, fb_depth_texture.gl_format, fb_depth_texture.gl_type, temp_gl_depth_buffer.get()); |
| 879 | 922 | ||
| 880 | for (int y = 0; y < fb_depth_texture.height; ++y) { | 923 | state.texture_units[0].texture_2d = 0; |
| 881 | for (int x = 0; x < fb_depth_texture.width; ++x) { | 924 | state.Apply(); |
| 882 | const u32 coarse_y = y & ~7; | 925 | |
| 883 | u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel; | 926 | u8* temp_gl_depth_data = bytes_per_pixel == 3 ? (temp_gl_depth_buffer.get() + 1) : temp_gl_depth_buffer.get(); |
| 884 | u32 gl_px_idx = x + y * fb_depth_texture.width; | 927 | |
| 885 | 928 | if (fb_depth_texture.format == Pica::Regs::DepthFormat::D24S8) { | |
| 886 | switch (fb_depth_texture.format) { | 929 | for (int y = 0; y < fb_depth_texture.height; ++y) { |
| 887 | case Pica::Regs::DepthFormat::D16: | 930 | for (int x = 0; x < fb_depth_texture.width; ++x) { |
| 888 | Color::EncodeD16(((u16*)temp_gl_depth_buffer.get())[gl_px_idx], depth_buffer + dst_offset); | 931 | const u32 coarse_y = y & ~7; |
| 889 | break; | 932 | u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel; |
| 890 | case Pica::Regs::DepthFormat::D24: | 933 | u32 gl_pixel_index = (x + y * fb_depth_texture.width); |
| 891 | Color::EncodeD24(((u32*)temp_gl_depth_buffer.get())[gl_px_idx], depth_buffer + dst_offset); | 934 | |
| 892 | break; | 935 | u8* pixel = depth_buffer + dst_offset; |
| 893 | case Pica::Regs::DepthFormat::D24S8: | 936 | u32 depth_stencil = ((u32*)temp_gl_depth_data)[gl_pixel_index]; |
| 894 | { | 937 | *(u32*)pixel = (depth_stencil >> 8) | (depth_stencil << 24); |
| 895 | u32 depth_stencil = ((u32*)temp_gl_depth_buffer.get())[gl_px_idx]; | ||
| 896 | Color::EncodeD24S8((depth_stencil >> 8), depth_stencil & 0xFF, depth_buffer + dst_offset); | ||
| 897 | break; | ||
| 898 | } | 938 | } |
| 899 | default: | 939 | } |
| 900 | LOG_CRITICAL(Render_OpenGL, "Unknown framebuffer depth format %x", fb_depth_texture.format); | 940 | } else { |
| 901 | UNIMPLEMENTED(); | 941 | for (int y = 0; y < fb_depth_texture.height; ++y) { |
| 902 | break; | 942 | for (int x = 0; x < fb_depth_texture.width; ++x) { |
| 943 | const u32 coarse_y = y & ~7; | ||
| 944 | u32 dst_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * fb_depth_texture.width * bytes_per_pixel; | ||
| 945 | u32 gl_pixel_index = (x + y * fb_depth_texture.width) * gl_bpp; | ||
| 946 | |||
| 947 | u8* pixel = depth_buffer + dst_offset; | ||
| 948 | memcpy(pixel, &temp_gl_depth_data[gl_pixel_index], bytes_per_pixel); | ||
| 903 | } | 949 | } |
| 904 | } | 950 | } |
| 905 | } | 951 | } |
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 9c5f38f94..3526e16d5 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp | |||
| @@ -16,6 +16,11 @@ OpenGLState::OpenGLState() { | |||
| 16 | depth.test_func = GL_LESS; | 16 | depth.test_func = GL_LESS; |
| 17 | depth.write_mask = GL_TRUE; | 17 | depth.write_mask = GL_TRUE; |
| 18 | 18 | ||
| 19 | color_mask.red_enabled = GL_TRUE; | ||
| 20 | color_mask.green_enabled = GL_TRUE; | ||
| 21 | color_mask.blue_enabled = GL_TRUE; | ||
| 22 | color_mask.alpha_enabled = GL_TRUE; | ||
| 23 | |||
| 19 | stencil.test_enabled = false; | 24 | stencil.test_enabled = false; |
| 20 | stencil.test_func = GL_ALWAYS; | 25 | stencil.test_func = GL_ALWAYS; |
| 21 | stencil.test_ref = 0; | 26 | stencil.test_ref = 0; |
| @@ -77,6 +82,15 @@ void OpenGLState::Apply() { | |||
| 77 | glDepthMask(depth.write_mask); | 82 | glDepthMask(depth.write_mask); |
| 78 | } | 83 | } |
| 79 | 84 | ||
| 85 | // Color mask | ||
| 86 | if (color_mask.red_enabled != cur_state.color_mask.red_enabled || | ||
| 87 | color_mask.green_enabled != cur_state.color_mask.green_enabled || | ||
| 88 | color_mask.blue_enabled != cur_state.color_mask.blue_enabled || | ||
| 89 | color_mask.alpha_enabled != cur_state.color_mask.alpha_enabled) { | ||
| 90 | glColorMask(color_mask.red_enabled, color_mask.green_enabled, | ||
| 91 | color_mask.blue_enabled, color_mask.alpha_enabled); | ||
| 92 | } | ||
| 93 | |||
| 80 | // Stencil test | 94 | // Stencil test |
| 81 | if (stencil.test_enabled != cur_state.stencil.test_enabled) { | 95 | if (stencil.test_enabled != cur_state.stencil.test_enabled) { |
| 82 | if (stencil.test_enabled) { | 96 | if (stencil.test_enabled) { |
| @@ -87,8 +101,8 @@ void OpenGLState::Apply() { | |||
| 87 | } | 101 | } |
| 88 | 102 | ||
| 89 | if (stencil.test_func != cur_state.stencil.test_func || | 103 | if (stencil.test_func != cur_state.stencil.test_func || |
| 90 | stencil.test_ref != cur_state.stencil.test_ref || | 104 | stencil.test_ref != cur_state.stencil.test_ref || |
| 91 | stencil.test_mask != cur_state.stencil.test_mask) { | 105 | stencil.test_mask != cur_state.stencil.test_mask) { |
| 92 | glStencilFunc(stencil.test_func, stencil.test_ref, stencil.test_mask); | 106 | glStencilFunc(stencil.test_func, stencil.test_ref, stencil.test_mask); |
| 93 | } | 107 | } |
| 94 | 108 | ||
| @@ -112,17 +126,19 @@ void OpenGLState::Apply() { | |||
| 112 | } | 126 | } |
| 113 | 127 | ||
| 114 | if (blend.color.red != cur_state.blend.color.red || | 128 | if (blend.color.red != cur_state.blend.color.red || |
| 115 | blend.color.green != cur_state.blend.color.green || | 129 | blend.color.green != cur_state.blend.color.green || |
| 116 | blend.color.blue != cur_state.blend.color.blue || | 130 | blend.color.blue != cur_state.blend.color.blue || |
| 117 | blend.color.alpha != cur_state.blend.color.alpha) { | 131 | blend.color.alpha != cur_state.blend.color.alpha) { |
| 118 | glBlendColor(blend.color.red, blend.color.green, blend.color.blue, blend.color.alpha); | 132 | glBlendColor(blend.color.red, blend.color.green, |
| 133 | blend.color.blue, blend.color.alpha); | ||
| 119 | } | 134 | } |
| 120 | 135 | ||
| 121 | if (blend.src_rgb_func != cur_state.blend.src_rgb_func || | 136 | if (blend.src_rgb_func != cur_state.blend.src_rgb_func || |
| 122 | blend.dst_rgb_func != cur_state.blend.dst_rgb_func || | 137 | blend.dst_rgb_func != cur_state.blend.dst_rgb_func || |
| 123 | blend.src_a_func != cur_state.blend.src_a_func || | 138 | blend.src_a_func != cur_state.blend.src_a_func || |
| 124 | blend.dst_a_func != cur_state.blend.dst_a_func) { | 139 | blend.dst_a_func != cur_state.blend.dst_a_func) { |
| 125 | glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func, blend.dst_a_func); | 140 | glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func, |
| 141 | blend.src_a_func, blend.dst_a_func); | ||
| 126 | } | 142 | } |
| 127 | 143 | ||
| 128 | if (logic_op != cur_state.logic_op) { | 144 | if (logic_op != cur_state.logic_op) { |
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 6b97721d6..26b916360 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h | |||
| @@ -20,6 +20,13 @@ public: | |||
| 20 | } depth; | 20 | } depth; |
| 21 | 21 | ||
| 22 | struct { | 22 | struct { |
| 23 | GLboolean red_enabled; | ||
| 24 | GLboolean green_enabled; | ||
| 25 | GLboolean blue_enabled; | ||
| 26 | GLboolean alpha_enabled; | ||
| 27 | } color_mask; // GL_COLOR_WRITEMASK | ||
| 28 | |||
| 29 | struct { | ||
| 23 | bool test_enabled; // GL_STENCIL_TEST | 30 | bool test_enabled; // GL_STENCIL_TEST |
| 24 | GLenum test_func; // GL_STENCIL_FUNC | 31 | GLenum test_func; // GL_STENCIL_FUNC |
| 25 | GLint test_ref; // GL_STENCIL_REF | 32 | GLint test_ref; // GL_STENCIL_REF |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 382aeaa05..058ad12cd 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -170,6 +170,9 @@ void RendererOpenGL::LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig& | |||
| 170 | texture.gl_format, texture.gl_type, framebuffer_data); | 170 | texture.gl_format, texture.gl_type, framebuffer_data); |
| 171 | 171 | ||
| 172 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); | 172 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); |
| 173 | |||
| 174 | state.texture_units[0].texture_2d = 0; | ||
| 175 | state.Apply(); | ||
| 173 | } | 176 | } |
| 174 | 177 | ||
| 175 | /** | 178 | /** |
| @@ -239,6 +242,9 @@ void RendererOpenGL::InitOpenGLObjects() { | |||
| 239 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 242 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 240 | } | 243 | } |
| 241 | 244 | ||
| 245 | state.texture_units[0].texture_2d = 0; | ||
| 246 | state.Apply(); | ||
| 247 | |||
| 242 | hw_rasterizer->InitObjects(); | 248 | hw_rasterizer->InitObjects(); |
| 243 | } | 249 | } |
| 244 | 250 | ||