summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/citra_qt/CMakeLists.txt8
-rw-r--r--src/common/math_util.h2
-rw-r--r--src/core/arm/skyeye_common/arm_regformat.h2
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.cpp4
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.h1
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp18
-rw-r--r--src/video_core/pica.h6
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp154
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp36
-rw-r--r--src/video_core/renderer_opengl/gl_state.h7
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp6
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
14inline bool IntervalsIntersect(unsigned start0, unsigned length0, unsigned start1, unsigned length1) { 14inline 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
18template<typename T> 18template<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
1069VMOVBRC_INST: 1069VMOVBRC_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
1196VMOVBCR_INST: 1196VMOVBCR_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
211void RasterizerOpenGL::CommitFramebuffer() { 235void 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
477void RasterizerOpenGL::ReconfigureDepthTexture(DepthTextureInfo& texture, Pica::Regs::DepthFormat format, u32 width, u32 height) { 504void 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
518void RasterizerOpenGL::SyncFramebuffer() { 548void 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
778void RasterizerOpenGL::ReloadDepthBuffer() { 815void 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
829void RasterizerOpenGL::CommitColorBuffer() { 869void 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