From b19e02ee41912bc5f400ba9bb739a2255a6da7e1 Mon Sep 17 00:00:00 2001 From: Logan McNaughton Date: Sat, 13 Jun 2020 23:40:04 -0600 Subject: [PATCH] update gliden64 --- GLideN64/src/Graphics/Context.cpp | 9 +- GLideN64/src/Graphics/Context.h | 6 +- GLideN64/src/Graphics/ContextImpl.h | 1 + .../Graphics/OpenGLContext/GLFunctions.cpp | 4 + .../src/Graphics/OpenGLContext/GLFunctions.h | 2 + .../GLSL/glsl_CombinerProgramBuilder.cpp | 164 ++++++++++++++---- .../GLSL/glsl_CombinerProgramBuilder.h | 1 + .../glsl_CombinerProgramUniformFactory.cpp | 70 +++++--- .../GLSL/glsl_SpecialShadersFactory.cpp | 3 +- .../ThreadedOpenGl/opengl_WrappedFunctions.h | 36 ++++ .../ThreadedOpenGl/opengl_Wrapper.cpp | 9 + .../ThreadedOpenGl/opengl_Wrapper.h | 1 + .../OpenGLContext/opengl_CachedFunctions.cpp | 15 ++ .../OpenGLContext/opengl_CachedFunctions.h | 10 ++ .../OpenGLContext/opengl_ContextImpl.cpp | 9 + .../OpenGLContext/opengl_ContextImpl.h | 2 + .../Graphics/OpenGLContext/opengl_GLInfo.cpp | 2 + .../Graphics/OpenGLContext/opengl_GLInfo.h | 1 + .../OpenGLContext/opengl_Parameters.cpp | 4 + GLideN64/src/Graphics/Parameters.h | 4 + GLideN64/src/GraphicsDrawer.cpp | 123 ++++++++----- GLideN64/src/GraphicsDrawer.h | 7 +- GLideN64/src/RSP_LoadMatrixX86.cpp | 3 +- GLideN64/src/TexrectDrawer.cpp | 2 +- 24 files changed, 378 insertions(+), 110 deletions(-) diff --git a/GLideN64/src/Graphics/Context.cpp b/GLideN64/src/Graphics/Context.cpp index 02979fc..3f6219d 100644 --- a/GLideN64/src/Graphics/Context.cpp +++ b/GLideN64/src/Graphics/Context.cpp @@ -17,6 +17,7 @@ bool Context::FramebufferFetch = false; bool Context::TextureBarrier = false; bool Context::EglImage = false; bool Context::EglImageFramebuffer = false; +bool Context::DualSourceBlending = false; Context::Context() {} @@ -41,7 +42,8 @@ void Context::init() FramebufferFetch = m_impl->isSupported(SpecialFeatures::FramebufferFetch); TextureBarrier = m_impl->isSupported(SpecialFeatures::TextureBarrier); EglImage = m_impl->isSupported(SpecialFeatures::EglImage); - EglImageFramebuffer = m_impl->isSupported(SpecialFeatures::EglImageFramebuffer); + EglImageFramebuffer = m_impl->isSupported(SpecialFeatures::EglImageFramebuffer); + DualSourceBlending = m_impl->isSupported(SpecialFeatures::DualSourceBlending); } void Context::destroy() @@ -100,6 +102,11 @@ void Context::setBlending(BlendParam _sfactor, BlendParam _dfactor) m_impl->setBlending(_sfactor, _dfactor); } +void graphics::Context::setBlendingSeparate(BlendParam _sfactorcolor, BlendParam _dfactorcolor, BlendParam _sfactoralpha, BlendParam _dfactoralpha) +{ + m_impl->setBlendingSeparate(_sfactorcolor, _dfactorcolor, _sfactoralpha, _dfactoralpha); +} + void Context::setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha) { m_impl->setBlendColor(_red, _green, _blue, _alpha); diff --git a/GLideN64/src/Graphics/Context.h b/GLideN64/src/Graphics/Context.h index ed8ea47..3cab2eb 100644 --- a/GLideN64/src/Graphics/Context.h +++ b/GLideN64/src/Graphics/Context.h @@ -27,7 +27,8 @@ namespace graphics { FramebufferFetch, TextureBarrier, EglImage, - EglImageFramebuffer + EglImageFramebuffer, + DualSourceBlending }; enum class ClampMode { @@ -69,6 +70,8 @@ namespace graphics { void setBlending(BlendParam _sfactor, BlendParam _dfactor); + void setBlendingSeparate(BlendParam _sfactorcolor, BlendParam _dfactorcolor, BlendParam _sfactoralpha, BlendParam _dfactoralpha); + void setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha); void clearColorBuffer(f32 _red, f32 _green, f32 _blue, f32 _alpha); @@ -300,6 +303,7 @@ namespace graphics { static bool TextureBarrier; static bool EglImage; static bool EglImageFramebuffer; + static bool DualSourceBlending; private: std::unique_ptr m_impl; diff --git a/GLideN64/src/Graphics/ContextImpl.h b/GLideN64/src/Graphics/ContextImpl.h index d56e4a1..d7126e6 100644 --- a/GLideN64/src/Graphics/ContextImpl.h +++ b/GLideN64/src/Graphics/ContextImpl.h @@ -22,6 +22,7 @@ namespace graphics { virtual void setViewport(s32 _x, s32 _y, s32 _width, s32 _height) = 0; virtual void setScissor(s32 _x, s32 _y, s32 _width, s32 _height) = 0; virtual void setBlending(BlendParam _sfactor, BlendParam _dfactor) = 0; + virtual void setBlendingSeparate(BlendParam _sfactorcolor, BlendParam _dfactorcolor, BlendParam _sfactoralpha, BlendParam _dfactoralpha) = 0; virtual void setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha) = 0; virtual void clearColorBuffer(f32 _red, f32 _green, f32 _blue, f32 _alpha) = 0; virtual void clearDepthBuffer() = 0; diff --git a/GLideN64/src/Graphics/OpenGLContext/GLFunctions.cpp b/GLideN64/src/Graphics/OpenGLContext/GLFunctions.cpp index fb4f1a7..dbca83b 100644 --- a/GLideN64/src/Graphics/OpenGLContext/GLFunctions.cpp +++ b/GLideN64/src/Graphics/OpenGLContext/GLFunctions.cpp @@ -62,6 +62,7 @@ static void* IOSGLGetProcAddress (const char *name) //GL Functions PFNGLBLENDFUNCPROC ptrBlendFunc; +PFNGLBLENDFUNCSEPARATEPROC ptrBlendFuncSeparate; PFNGLPIXELSTOREIPROC ptrPixelStorei; PFNGLCLEARCOLORPROC ptrClearColor; PFNGLCULLFACEPROC ptrCullFace; @@ -388,4 +389,7 @@ void initGLFunctions() GL_GET_PROC_ADR(PFNGLEGLIMAGETARGETTEXTURE2DOESPROC, EGLImageTargetTexture2DOES); GL_GET_PROC_ADR(PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC, EGLImageTargetRenderbufferStorageOES); + + GL_GET_PROC_ADR(PFNGLBLENDFUNCSEPARATEPROC, BlendFuncSeparate); + } diff --git a/GLideN64/src/Graphics/OpenGLContext/GLFunctions.h b/GLideN64/src/Graphics/OpenGLContext/GLFunctions.h index caf4aff..f39efde 100644 --- a/GLideN64/src/Graphics/OpenGLContext/GLFunctions.h +++ b/GLideN64/src/Graphics/OpenGLContext/GLFunctions.h @@ -52,6 +52,7 @@ typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GL #endif extern PFNGLBLENDFUNCPROC ptrBlendFunc; +extern PFNGLBLENDFUNCSEPARATEPROC ptrBlendFuncSeparate; extern PFNGLPIXELSTOREIPROC ptrPixelStorei; extern PFNGLCLEARCOLORPROC ptrClearColor; extern PFNGLCULLFACEPROC ptrCullFace; @@ -203,6 +204,7 @@ void initGLFunctions(); #define glGetError(...) opengl::FunctionWrapper::wrGetError(__VA_ARGS__) #define glBlendFunc(...) opengl::FunctionWrapper::wrBlendFunc(__VA_ARGS__) +#define glBlendFuncSeparate(...) opengl::FunctionWrapper::wrBlendFuncSeparate(__VA_ARGS__) #define glPixelStorei(...) opengl::FunctionWrapper::wrPixelStorei(__VA_ARGS__) #define glClearColor(...) opengl::FunctionWrapper::wrClearColor(__VA_ARGS__) #define glCullFace(...) opengl::FunctionWrapper::wrCullFace(__VA_ARGS__) diff --git a/GLideN64/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp b/GLideN64/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp index 2cffd40..98c3abc 100644 --- a/GLideN64/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp +++ b/GLideN64/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp @@ -514,6 +514,8 @@ public: ss << "#version " << Utils::to_string(_glinfo.majorVersion) << Utils::to_string(_glinfo.minorVersion) << "0 es " << std::endl; if (_glinfo.noPerspective) ss << "#extension GL_NV_shader_noperspective_interpolation : enable" << std::endl; + if (_glinfo.dual_source_blending) + ss << "#extension GL_EXT_blend_func_extended : enable" << std::endl; if (config.frameBufferEmulation.N64DepthCompare == Config::dcFast) { if (_glinfo.imageTextures && _glinfo.fragment_interlockNV) { ss << "#extension GL_NV_fragment_shader_interlock : enable" << std::endl @@ -560,21 +562,40 @@ public: class ShaderBlender1 : public ShaderPart { public: - ShaderBlender1() + ShaderBlender1(const opengl::GLInfo & _glinfo) { #if 1 - m_part = - " #define MUXA(pos) dot(muxA, STVEC(pos)) \n" - " #define MUXB(pos) dot(muxB, STVEC(pos)) \n" - " #define MUXPM(pos) muxPM*(STVEC(pos)) \n" - " muxPM[0] = clampedColor; \n" - " if (uForceBlendCycle1 != 0) { \n" - " muxA[0] = clampedColor.a; \n" - " muxB[0] = 1.0 - MUXA(uBlendMux1[1]); \n" - " lowp vec4 blend1 = MUXPM(uBlendMux1[0]) * MUXA(uBlendMux1[1]) + MUXPM(uBlendMux1[2]) * MUXB(uBlendMux1[3]); \n" - " clampedColor.rgb = clamp(blend1.rgb, 0.0, 1.0); \n" - " } else clampedColor.rgb = (MUXPM(uBlendMux1[0])).rgb; \n" + m_part = + " srcColor1 = vec4(0.0); \n" + " dstFactor1 = 0.0; \n" + " muxPM[0] = clampedColor; \n" + " muxA[0] = clampedColor.a; \n" + " muxa = MUXA(uBlendMux1[1]); \n" + " muxB[0] = 1.0 - muxa; \n" + " muxb = MUXB(uBlendMux1[3]); \n" + " muxp = MUXPM(uBlendMux1[0]); \n" + " muxm = MUXPM(uBlendMux1[2]); \n" + " muxaf = MUXF(uBlendMux1[0]); \n" + " muxbf = MUXF(uBlendMux1[2]); \n" + " if (uForceBlendCycle1 != 0) { \n" + " srcColor1 = muxp * muxa + muxm * muxb; \n" + " dstFactor1 = muxaf * muxa + muxbf * muxb; \n" + " srcColor1 = clamp(srcColor1, 0.0, 1.0); \n" + " } else { \n" + " srcColor1 = muxp; \n" + " dstFactor1 = muxaf; \n" + " } \n" + ; + if (_glinfo.dual_source_blending) { + m_part += + " fragColor = srcColor1; \n" + " fragColor1 = vec4(dstFactor1); \n" ; + } else { + m_part += + " fragColor = vec4(srcColor1.rgb, clampedColor.a); \n" + ; + } #else // Keep old code for reference m_part = @@ -593,19 +614,41 @@ public: class ShaderBlender2 : public ShaderPart { public: - ShaderBlender2() + ShaderBlender2(const opengl::GLInfo & _glinfo) { #if 1 m_part = - " muxPM[0] = clampedColor; \n" - " muxPM[1] = vec4(0.0); \n" - " if (uForceBlendCycle2 != 0) { \n" - " muxA[0] = clampedColor.a; \n" - " muxB[0] = 1.0 - MUXA(uBlendMux2[1]); \n" - " lowp vec4 blend2 = MUXPM(uBlendMux2[0]) * MUXA(uBlendMux2[1]) + MUXPM(uBlendMux2[2]) * MUXB(uBlendMux2[3]); \n" - " clampedColor.rgb = clamp(blend2.rgb, 0.0, 1.0); \n" - " } else clampedColor.rgb = (MUXPM(uBlendMux2[0])).rgb; \n" + " srcColor2 = vec4(0.0); \n" + " dstFactor2 = 0.0; \n" + " muxPM[0] = srcColor1; \n" + " muxa = MUXA(uBlendMux2[1]); \n" + " muxB[0] = 1.0 - muxa; \n" + " muxb = MUXB(uBlendMux2[3]); \n" + " muxp = MUXPM(uBlendMux2[0]); \n" + " muxm = MUXPM(uBlendMux2[2]); \n" + " muxF[0] = dstFactor1; \n" + " muxaf = MUXF(uBlendMux2[0]); \n" + " muxbf = MUXF(uBlendMux2[2]); \n" + " if (uForceBlendCycle2 != 0) { \n" + " srcColor2 = muxp * muxa + muxm * muxb; \n" + " dstFactor2 = muxaf * muxa + muxbf * muxb; \n" + " srcColor2 = clamp(srcColor2, 0.0, 1.0); \n" + " } else { \n" + " srcColor2 = muxp; \n" + " dstFactor2 = muxaf; \n" + " } \n" ; + if (_glinfo.dual_source_blending) { + m_part += + " fragColor = srcColor2; \n" + " fragColor1 = vec4(dstFactor2); \n" + ; + } else { + m_part += + " fragColor = vec4(srcColor2.rgb, clampedColor.a); \n" + ; + } + #else // Keep old code for reference m_part = @@ -622,6 +665,26 @@ public: } }; +class ShaderBlenderAlpha : public ShaderPart +{ +public: + ShaderBlenderAlpha(const opengl::GLInfo & _glinfo) + { + if (_glinfo.dual_source_blending) + m_part += + "if (uBlendAlphaMode != 2) { \n" + " lowp float cvg = clampedColor.a; \n" + " lowp vec4 srcAlpha = vec4(cvg, cvg, 1.0, 0.0); \n" + " lowp vec4 dstFactorAlpha = vec4(1.0, 1.0, 0.0, 1.0); \n" + " if (uBlendAlphaMode == 0) \n" + " dstFactorAlpha[0] = 0.0; \n" + " fragColor.a = srcAlpha[uCvgDest]; \n" + " fragColor1.a = dstFactorAlpha[uCvgDest]; \n" + "} else fragColor.a = clampedColor.a; \n" + ; + } +}; + class ShaderLegacyBlender : public ShaderPart { public: @@ -871,7 +934,9 @@ public: "highp vec2 texCoord1; \n" "highp vec2 tcData0[5]; \n" "highp vec2 tcData1[5]; \n" - ; + "uniform lowp int uCvgDest; \n" + "uniform lowp int uBlendAlphaMode; \n" + ; if (config.generalEmulation.enableLegacyBlending != 0) { m_part += @@ -924,15 +989,21 @@ public: "IN lowp float vNumLights; \n" ; - if (config.frameBufferEmulation.N64DepthCompare == Config::dcFast && _glinfo.ext_fetch) { + if (_glinfo.dual_source_blending) { m_part += - "layout(location = 0) OUT lowp vec4 fragColor; \n" - "layout(location = 1) inout highp vec4 depthZ; \n" - "layout(location = 2) inout highp vec4 depthDeltaZ; \n" + "layout(location = 0, index = 0) OUT lowp vec4 fragColor; \n" + "layout(location = 0, index = 1) OUT lowp vec4 fragColor1; \n" ; } else { m_part += "OUT lowp vec4 fragColor; \n" + ; + } + + if (config.frameBufferEmulation.N64DepthCompare == Config::dcFast && _glinfo.ext_fetch) { + m_part += + "layout(location = 1) inout highp vec4 depthZ; \n" + "layout(location = 2) inout highp vec4 depthDeltaZ; \n" ; } } @@ -964,6 +1035,9 @@ public: "uniform highp float uPrimDepth; \n" "uniform mediump vec2 uScreenScale; \n" "uniform lowp int uScreenSpaceTriangle; \n" + "uniform lowp int uCvgDest; \n" + "uniform lowp int uBlendAlphaMode; \n" + ; if (config.generalEmulation.enableLegacyBlending != 0) { @@ -1006,15 +1080,21 @@ public: "IN lowp float vNumLights; \n" ; - if (config.frameBufferEmulation.N64DepthCompare == Config::dcFast && _glinfo.ext_fetch) { + if (_glinfo.dual_source_blending) { m_part += - "layout(location = 0) OUT lowp vec4 fragColor; \n" - "layout(location = 1) inout highp vec4 depthZ; \n" - "layout(location = 2) inout highp vec4 depthDeltaZ; \n" + "layout(location = 0, index = 0) OUT lowp vec4 fragColor; \n" + "layout(location = 0, index = 1) OUT lowp vec4 fragColor1; \n" ; } else { m_part += "OUT lowp vec4 fragColor; \n" + ; + } + + if (config.frameBufferEmulation.N64DepthCompare == Config::dcFast && _glinfo.ext_fetch) { + m_part += + "layout(location = 1) inout highp vec4 depthZ; \n" + "layout(location = 2) inout highp vec4 depthDeltaZ; \n" ; } } @@ -1242,7 +1322,7 @@ public: " lowp vec4 c0 = c00 + tcData[4].s * (c10-c00); \\\n" " lowp vec4 c1 = c01 + tcData[4].s * (c11-c01); \\\n" " name = c0 + tcData[4].t * (c1-c0); \\\n" - " if(uEnableAlphaTest == 1) name.rgb /= name.a; \\\n" + " if(uEnableAlphaTest == 1) name.rgb /= name.a; \\\n" "} \n" ; break; @@ -1418,9 +1498,16 @@ public: { if (config.generalEmulation.enableLegacyBlending == 0) { m_part = + " #define MUXA(pos) dot(muxA, STVEC(pos)) \n" + " #define MUXB(pos) dot(muxB, STVEC(pos)) \n" + " #define MUXPM(pos) muxPM*(STVEC(pos)) \n" + " #define MUXF(pos) dot(muxF, STVEC(pos)) \n" " lowp mat4 muxPM = mat4(vec4(0.0), vec4(0.0), uBlendColor, uFogColor); \n" " lowp vec4 muxA = vec4(0.0, uFogColor.a, shadeColor.a, 0.0); \n" " lowp vec4 muxB = vec4(0.0, 1.0, 1.0, 0.0); \n" + " lowp vec4 muxF = vec4(0.0, 1.0, 0.0, 0.0); \n" + " lowp vec4 muxp, muxm, srcColor1, srcColor2; \n" + " lowp float muxa, muxb, dstFactor1, dstFactor2, muxaf, muxbf; \n" ; } } @@ -2572,12 +2659,14 @@ CombinerInputs CombinerProgramBuilder::compileCombiner(const CombinerKey & _key, m_callDither->write(ssShader); if (config.generalEmulation.enableLegacyBlending == 0) { - if (g_cycleType <= G_CYC_2CYCLE) + if (g_cycleType <= G_CYC_2CYCLE) { m_blender1->write(ssShader); - if (g_cycleType == G_CYC_2CYCLE) - m_blender2->write(ssShader); + if (g_cycleType == G_CYC_2CYCLE) + m_blender2->write(ssShader); + m_blenderAlpha->write(ssShader); + } else + ssShader << " fragColor = clampedColor;" << std::endl; - ssShader << " fragColor = clampedColor;" << std::endl; } else { ssShader << " fragColor = clampedColor;" << std::endl; @@ -2792,8 +2881,9 @@ GLuint _createVertexShader(ShaderPart * _header, ShaderPart * _body, ShaderPart } CombinerProgramBuilder::CombinerProgramBuilder(const opengl::GLInfo & _glinfo, opengl::CachedUseProgram * _useProgram) -: m_blender1(new ShaderBlender1) -, m_blender2(new ShaderBlender2) +: m_blender1(new ShaderBlender1(_glinfo)) +, m_blender2(new ShaderBlender2(_glinfo)) +, m_blenderAlpha (new ShaderBlenderAlpha(_glinfo)) , m_legacyBlender(new ShaderLegacyBlender) , m_clamp(new ShaderClamp) , m_signExtendColorC(new ShaderSignExtendColorC) diff --git a/GLideN64/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.h b/GLideN64/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.h index f69fe92..b7f8bf3 100644 --- a/GLideN64/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.h +++ b/GLideN64/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.h @@ -39,6 +39,7 @@ namespace glsl { typedef std::unique_ptr ShaderPartPtr; ShaderPartPtr m_blender1; ShaderPartPtr m_blender2; + ShaderPartPtr m_blenderAlpha; ShaderPartPtr m_legacyBlender; ShaderPartPtr m_clamp; ShaderPartPtr m_signExtendColorC; diff --git a/GLideN64/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp b/GLideN64/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp index 7ab5881..1f46afd 100644 --- a/GLideN64/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp +++ b/GLideN64/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp @@ -369,30 +369,33 @@ public: const int forceBlend2 = gDP.otherMode.forceBlender; uForceBlendCycle2.set(forceBlend2, _force); - // Modes, which shader blender can't emulate - const u32 mode = _SHIFTR(gDP.otherMode.l, 16, 16); - switch (mode) { - case 0x0040: - // Mia Hamm Soccer - // clr_in * a_in + clr_mem * (1-a) - // clr_in * a_in + clr_in * (1-a) - case 0x0050: - // A Bug's Life - // clr_in * a_in + clr_mem * (1-a) - // clr_in * a_in + clr_mem * (1-a) - uForceBlendCycle1.set(0, _force); - uForceBlendCycle2.set(0, _force); - break; - case 0x0150: - // Tony Hawk - // clr_in * a_in + clr_mem * (1-a) - // clr_in * a_fog + clr_mem * (1-a_fog) - if ((config.generalEmulation.hacks & hack_TonyHawk) != 0) { + if (!graphics::Context::DualSourceBlending || dwnd().getDrawer().isTexrectDrawerMode()) { + // Modes, which shader blender can't emulate + const u32 mode = _SHIFTR(gDP.otherMode.l, 16, 16); + switch (mode) { + case 0x0040: + // Mia Hamm Soccer + // clr_in * a_in + clr_mem * (1-a) + // clr_in * a_in + clr_in * (1-a) + case 0x0050: + // A Bug's Life + // clr_in * a_in + clr_mem * (1-a) + // clr_in * a_in + clr_mem * (1-a) uForceBlendCycle1.set(0, _force); uForceBlendCycle2.set(0, _force); + break; + case 0x0150: + // Tony Hawk + // clr_in * a_in + clr_mem * (1-a) + // clr_in * a_fog + clr_mem * (1-a_fog) + if ((config.generalEmulation.hacks & hack_TonyHawk) != 0) { + uForceBlendCycle1.set(0, _force); + uForceBlendCycle2.set(0, _force); + } + break; } - break; } + } private: @@ -402,6 +405,27 @@ private: iUniform uForceBlendCycle2; }; +class UBlendCvg : public UniformGroup +{ +public: + UBlendCvg(GLuint _program) { + LocateUniform(uCvgDest); + LocateUniform(uBlendAlphaMode); + } + + void update(bool _force) override + { + uCvgDest.set(gDP.otherMode.cvgDest, _force); + if (dwnd().getDrawer().isTexrectDrawerMode()) + uBlendAlphaMode.set(2, _force); // No alpha blend in texrect drawing mode + else + uBlendAlphaMode.set(gDP.otherMode.forceBlender, _force); + } +private: + iUniform uCvgDest; + iUniform uBlendAlphaMode; +}; + class UDitherMode : public UniformGroup { public: @@ -979,7 +1003,7 @@ public: CachedTexture * pTexture = cache.current[tile]; if (pTile == nullptr || pTexture == nullptr) continue; - + aTexSize[t][0] = pTexture->width * pTexture->hdRatioS; aTexSize[t][1] = pTexture->height * pTexture->hdRatioT; @@ -1024,7 +1048,7 @@ public: uTexMirrorEn1.set(aTexMirrorEn[1][0], aTexMirrorEn[1][1], _force); uTexSize0.set(aTexSize[0][0], aTexSize[0][1], _force); uTexSize1.set(aTexSize[1][0], aTexSize[1][1], _force); - + } private: @@ -1126,6 +1150,8 @@ void CombinerProgramUniformFactory::buildUniforms(GLuint _program, } } + _uniforms.emplace_back(new UBlendCvg(_program)); + _uniforms.emplace_back(new UDitherMode(_program, _inputs.usesNoise())); _uniforms.emplace_back(new UScreenScale(_program)); diff --git a/GLideN64/src/Graphics/OpenGLContext/GLSL/glsl_SpecialShadersFactory.cpp b/GLideN64/src/Graphics/OpenGLContext/GLSL/glsl_SpecialShadersFactory.cpp index c400f8e..a5ccc96 100644 --- a/GLideN64/src/Graphics/OpenGLContext/GLSL/glsl_SpecialShadersFactory.cpp +++ b/GLideN64/src/Graphics/OpenGLContext/GLSL/glsl_SpecialShadersFactory.cpp @@ -313,8 +313,7 @@ namespace glsl { "{ \n" " TEX_FILTER(fragColor, uTex0, vTexCoord0); \n" ; - if (!_glinfo.isGLES2 && - config.generalEmulation.enableFragmentDepthWrite != 0 && + if (config.generalEmulation.enableFragmentDepthWrite != 0 && config.frameBufferEmulation.N64DepthCompare == Config::dcDisable) { m_part += " gl_FragDepth = uPrimDepth; \n" diff --git a/GLideN64/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_WrappedFunctions.h b/GLideN64/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_WrappedFunctions.h index 4c87d36..05ad185 100644 --- a/GLideN64/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_WrappedFunctions.h +++ b/GLideN64/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_WrappedFunctions.h @@ -58,6 +58,42 @@ private: GLenum m_dfactor; }; +class GlBlendFuncSeparateCommand : public OpenGlCommand +{ +public: + GlBlendFuncSeparateCommand() : + OpenGlCommand(false, false, "glBlendFuncSeparate") + { + } + + static std::shared_ptr get(GLenum sfactorcolor, GLenum dfactorcolor, GLenum sfactoralpha, GLenum dfactoralpha) + { + static int poolId = OpenGlCommandPool::get().getNextAvailablePool(); + auto ptr = getFromPool(poolId); + ptr->set(sfactorcolor, dfactorcolor, sfactoralpha, dfactoralpha); + return ptr; + } + + void commandToExecute() override + { + ptrBlendFuncSeparate(m_sfactorcolor, m_dfactorcolor, m_sfactoralpha, m_dfactoralpha); + } +private: + void set(GLenum sfactorcolor, GLenum dfactorcolor, GLenum sfactoralpha, GLenum dfactoralpha) + { + m_sfactorcolor = sfactorcolor; + m_dfactorcolor = dfactorcolor; + m_sfactoralpha = sfactoralpha; + m_dfactoralpha = dfactoralpha; + } + + GLenum m_sfactorcolor; + GLenum m_dfactorcolor; + GLenum m_sfactoralpha; + GLenum m_dfactoralpha; +}; + + class GlPixelStoreiCommand : public OpenGlCommand { public: diff --git a/GLideN64/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Wrapper.cpp b/GLideN64/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Wrapper.cpp index 30858fd..5d9e08a 100644 --- a/GLideN64/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Wrapper.cpp +++ b/GLideN64/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Wrapper.cpp @@ -144,6 +144,15 @@ namespace opengl { ptrBlendFunc(sfactor, dfactor); } + void FunctionWrapper::wrBlendFuncSeparate(GLenum sfactorcolor, GLenum dfactorcolor, GLenum sfactoralpha, GLenum dfactoralpha) + { + if (m_threaded_wrapper) + executeCommand(GlBlendFuncSeparateCommand::get(sfactorcolor, dfactorcolor, sfactoralpha, dfactoralpha)); + else + ptrBlendFuncSeparate(sfactorcolor, dfactorcolor, sfactoralpha, dfactoralpha); + } + + void FunctionWrapper::wrPixelStorei(GLenum pname, GLint param) { if (m_threaded_wrapper) diff --git a/GLideN64/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Wrapper.h b/GLideN64/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Wrapper.h index 733d57e..39998c3 100644 --- a/GLideN64/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Wrapper.h +++ b/GLideN64/src/Graphics/OpenGLContext/ThreadedOpenGl/opengl_Wrapper.h @@ -59,6 +59,7 @@ namespace opengl { static void setThreadedMode(u32 _threaded); static void wrBlendFunc(GLenum sfactor, GLenum dfactor); + static void wrBlendFuncSeparate(GLenum sfactorcolor, GLenum dfactorcolor, GLenum sfactoralpha, GLenum dfactoralpha); static void wrPixelStorei(GLenum pname, GLint param); static void wrClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); static void wrCullFace(GLenum mode); diff --git a/GLideN64/src/Graphics/OpenGLContext/opengl_CachedFunctions.cpp b/GLideN64/src/Graphics/OpenGLContext/opengl_CachedFunctions.cpp index 9d15886..43f6ce1 100644 --- a/GLideN64/src/Graphics/OpenGLContext/opengl_CachedFunctions.cpp +++ b/GLideN64/src/Graphics/OpenGLContext/opengl_CachedFunctions.cpp @@ -119,6 +119,15 @@ void CachedBlending::setBlending(Parameter _sfactor, Parameter _dfactor) glBlendFunc(GLenum(_sfactor), GLenum(_dfactor)); } +/*---------------CachedBlendingSeparate-------------*/ + +void CachedBlendingSeparate::setBlendingSeparate(Parameter _sfactorcolor, Parameter _dfactorcolor, Parameter _sfactoralpha, Parameter _dfactoralpha) +{ + if (update(_sfactorcolor, _dfactorcolor, _sfactoralpha, _dfactoralpha)) + glBlendFuncSeparate(GLenum(_sfactorcolor), GLenum(_dfactorcolor), GLenum(_sfactoralpha), GLenum(_dfactoralpha)); +} + + /*---------------CachedBlendColor-------------*/ void CachedBlendColor::setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha) @@ -269,6 +278,12 @@ CachedBlending * CachedFunctions::getCachedBlending() return &m_blending; } +CachedBlendingSeparate * CachedFunctions::getCachedBlendingSeparate() +{ + return &m_blendingseparate; +} + + CachedBlendColor * CachedFunctions::getCachedBlendColor() { return &m_blendColor; diff --git a/GLideN64/src/Graphics/OpenGLContext/opengl_CachedFunctions.h b/GLideN64/src/Graphics/OpenGLContext/opengl_CachedFunctions.h index 95f6420..2afa407 100644 --- a/GLideN64/src/Graphics/OpenGLContext/opengl_CachedFunctions.h +++ b/GLideN64/src/Graphics/OpenGLContext/opengl_CachedFunctions.h @@ -170,6 +170,13 @@ namespace opengl { void setBlending(graphics::Parameter _sfactor, graphics::Parameter _dfactor); }; + class CachedBlendingSeparate : public Cached4 // + { + public: + void setBlendingSeparate(graphics::Parameter _sfactorcolor, graphics::Parameter _dfactorcolor, graphics::Parameter _sfactoralpha, graphics::Parameter _dfactoralpha); + }; + + class CachedBlendColor : public Cached4 { public: @@ -246,6 +253,8 @@ namespace opengl { CachedScissor * getCachedScissor(); CachedBlending * getCachedBlending(); + + CachedBlendingSeparate * getCachedBlendingSeparate(); CachedBlendColor * getCachedBlendColor(); @@ -274,6 +283,7 @@ namespace opengl { CachedViewport m_viewport; CachedScissor m_scissor; CachedBlending m_blending; + CachedBlendingSeparate m_blendingseparate; CachedBlendColor m_blendColor; CachedClearColor m_clearColor; CachedVertexAttribArray m_attribArray; diff --git a/GLideN64/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp b/GLideN64/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp index 8498df0..b481c9d 100644 --- a/GLideN64/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp +++ b/GLideN64/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp @@ -156,6 +156,13 @@ void ContextImpl::setScissor(s32 _x, s32 _y, s32 _width, s32 _height) void ContextImpl::setBlending(graphics::BlendParam _sfactor, graphics::BlendParam _dfactor) { m_cachedFunctions->getCachedBlending()->setBlending(_sfactor, _dfactor); + m_cachedFunctions->getCachedBlendingSeparate()->reset(); +} + +void ContextImpl::setBlendingSeparate(graphics::BlendParam _sfactorcolor, graphics::BlendParam _dfactorcolor, graphics::BlendParam _sfactoralpha, graphics::BlendParam _dfactoralpha) +{ + m_cachedFunctions->getCachedBlendingSeparate()->setBlendingSeparate(_sfactorcolor, _dfactorcolor, _sfactoralpha, _dfactoralpha); + m_cachedFunctions->getCachedBlending()->reset(); } void ContextImpl::setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha) @@ -513,6 +520,8 @@ bool ContextImpl::isSupported(graphics::SpecialFeatures _feature) const return m_glInfo.eglImage; case graphics::SpecialFeatures::EglImageFramebuffer: return m_glInfo.eglImageFramebuffer; + case graphics::SpecialFeatures::DualSourceBlending: + return m_glInfo.dual_source_blending; } return false; } diff --git a/GLideN64/src/Graphics/OpenGLContext/opengl_ContextImpl.h b/GLideN64/src/Graphics/OpenGLContext/opengl_ContextImpl.h index 074177b..f8407b3 100644 --- a/GLideN64/src/Graphics/OpenGLContext/opengl_ContextImpl.h +++ b/GLideN64/src/Graphics/OpenGLContext/opengl_ContextImpl.h @@ -44,6 +44,8 @@ namespace opengl { void setBlending(graphics::BlendParam _sfactor, graphics::BlendParam _dfactor) override; + void setBlendingSeparate(graphics::BlendParam _sfactorcolor, graphics::BlendParam _dfactorcolor, graphics::BlendParam _sfactoralpha, graphics::BlendParam _dfactoralpha) override; + void setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha) override; void clearColorBuffer(f32 _red, f32 _green, f32 _blue, f32 _alpha) override; diff --git a/GLideN64/src/Graphics/OpenGLContext/opengl_GLInfo.cpp b/GLideN64/src/Graphics/OpenGLContext/opengl_GLInfo.cpp index b1a952c..1b4c526 100644 --- a/GLideN64/src/Graphics/OpenGLContext/opengl_GLInfo.cpp +++ b/GLideN64/src/Graphics/OpenGLContext/opengl_GLInfo.cpp @@ -162,6 +162,8 @@ void GLInfo::init() { ext_fetch = Utils::isExtensionSupported(*this, "GL_EXT_shader_framebuffer_fetch") && !isGLES2 && (!isGLESX || ext_draw_buffers_indexed) && !imageTexturesInterlock; eglImage = (Utils::isEGLExtensionSupported("EGL_KHR_image_base") || Utils::isEGLExtensionSupported("EGL_KHR_image")); + dual_source_blending = !(isGLESX) || Utils::isExtensionSupported(*this, "GL_EXT_blend_func_extended"); + #ifdef OS_ANDROID eglImage = eglImage && ( (isGLES2 && GraphicBufferWrapper::isSupportAvailable()) || (isGLESX && GraphicBufferWrapper::isPublicSupportAvailable()) ) && diff --git a/GLideN64/src/Graphics/OpenGLContext/opengl_GLInfo.h b/GLideN64/src/Graphics/OpenGLContext/opengl_GLInfo.h index 764c48b..6995924 100644 --- a/GLideN64/src/Graphics/OpenGLContext/opengl_GLInfo.h +++ b/GLideN64/src/Graphics/OpenGLContext/opengl_GLInfo.h @@ -35,6 +35,7 @@ struct GLInfo { bool ext_fetch = false; bool eglImage = false; bool eglImageFramebuffer = false; + bool dual_source_blending = false; Renderer renderer = Renderer::Other; void init(); diff --git a/GLideN64/src/Graphics/OpenGLContext/opengl_Parameters.cpp b/GLideN64/src/Graphics/OpenGLContext/opengl_Parameters.cpp index 2233894..ea8e449 100644 --- a/GLideN64/src/Graphics/OpenGLContext/opengl_Parameters.cpp +++ b/GLideN64/src/Graphics/OpenGLContext/opengl_Parameters.cpp @@ -117,6 +117,10 @@ namespace graphics { BlendParam ONE_MINUS_SRC_ALPHA(GL_ONE_MINUS_SRC_ALPHA); BlendParam CONSTANT_ALPHA(GL_CONSTANT_ALPHA); BlendParam ONE_MINUS_CONSTANT_ALPHA(GL_ONE_MINUS_CONSTANT_ALPHA); + BlendParam SRC1_COLOR(GL_SRC1_COLOR); + BlendParam ONE_MINUS_SRC1_COLOR(GL_ONE_MINUS_SRC1_COLOR); + BlendParam SRC1_ALPHA(GL_SRC1_ALPHA); + BlendParam ONE_MINUS_SRC1_ALPHA(GL_ONE_MINUS_SRC1_ALPHA); } namespace drawmode { diff --git a/GLideN64/src/Graphics/Parameters.h b/GLideN64/src/Graphics/Parameters.h index e8643e1..86f92a4 100644 --- a/GLideN64/src/Graphics/Parameters.h +++ b/GLideN64/src/Graphics/Parameters.h @@ -117,6 +117,10 @@ namespace graphics { extern BlendParam ONE_MINUS_SRC_ALPHA; extern BlendParam CONSTANT_ALPHA; extern BlendParam ONE_MINUS_CONSTANT_ALPHA; + extern BlendParam SRC1_COLOR; + extern BlendParam ONE_MINUS_SRC1_COLOR; + extern BlendParam SRC1_ALPHA; + extern BlendParam ONE_MINUS_SRC1_ALPHA; } namespace drawmode { diff --git a/GLideN64/src/GraphicsDrawer.cpp b/GLideN64/src/GraphicsDrawer.cpp index 2f044a6..12b982f 100644 --- a/GLideN64/src/GraphicsDrawer.cpp +++ b/GLideN64/src/GraphicsDrawer.cpp @@ -314,8 +314,7 @@ void GraphicsDrawer::_updateScreenCoordsViewport(const FrameBuffer * _pBuffer) c gSP.changed |= CHANGED_VIEWPORT; } -static -void _legacySetBlendMode() +void GraphicsDrawer::_legacyBlending() const { const u32 blendmode = gDP.otherMode.l >> 16; // 0x7000 = CVG_X_ALPHA|ALPHA_CVG_SEL|FORCE_BL @@ -478,48 +477,36 @@ void _legacySetBlendMode() } } -bool GraphicsDrawer::_setUnsupportedBlendMode() const +void GraphicsDrawer::_ordinaryBlending() const { - if (gDP.otherMode.cycleType != G_CYC_2CYCLE) - return false; - // Modes, which shader blender can't emulate - const u32 mode = _SHIFTR(gDP.otherMode.l, 16, 16); - switch (mode) { - case 0x0040: - // Mia Hamm Soccer - // clr_in * a_in + clr_mem * (1-a) - // clr_in * a_in + clr_in * (1-a) - case 0x0050: - // A Bug's Life - // clr_in * a_in + clr_mem * (1-a) - // clr_in * a_in + clr_mem * (1-a) - gfxContext.enable(enable::BLEND, true); - gfxContext.setBlending(blend::SRC_ALPHA, blend::ONE_MINUS_SRC_ALPHA); - return true; - case 0x0150: - // Tony Hawk - // clr_in * a_in + clr_mem * (1-a) - // clr_in * a_fog + clr_mem * (1-a_fog) - if ((config.generalEmulation.hacks & hack_TonyHawk) != 0) { + // Set unsupported blend modes + if (gDP.otherMode.cycleType == G_CYC_2CYCLE) { + const u32 mode = _SHIFTR(gDP.otherMode.l, 16, 16); + switch (mode) { + case 0x0040: + // Mia Hamm Soccer + // clr_in * a_in + clr_mem * (1-a) + // clr_in * a_in + clr_in * (1-a) + case 0x0050: + // A Bug's Life + // clr_in * a_in + clr_mem * (1-a) + // clr_in * a_in + clr_mem * (1-a) gfxContext.enable(enable::BLEND, true); gfxContext.setBlending(blend::SRC_ALPHA, blend::ONE_MINUS_SRC_ALPHA); - return true; + return; + case 0x0150: + // Tony Hawk + // clr_in * a_in + clr_mem * (1-a) + // clr_in * a_fog + clr_mem * (1-a_fog) + if ((config.generalEmulation.hacks & hack_TonyHawk) != 0) { + gfxContext.enable(enable::BLEND, true); + gfxContext.setBlending(blend::SRC_ALPHA, blend::ONE_MINUS_SRC_ALPHA); + return; + } + break; } - break; } - return false; -} - -void GraphicsDrawer::_setBlendMode() const -{ - if (config.generalEmulation.enableLegacyBlending != 0) { - _legacySetBlendMode(); - return; - } - - if (_setUnsupportedBlendMode()) - return; if (gDP.otherMode.forceBlender != 0 && gDP.otherMode.cycleType < G_CYC_COPY) { BlendParam srcFactor = blend::ONE; @@ -535,7 +522,8 @@ void GraphicsDrawer::_setBlendMode() const return; } memFactorSource = 0; - } else if (gDP.otherMode.c2_m2a == 1) { + } + else if (gDP.otherMode.c2_m2a == 1) { memFactorSource = 1; } if (gDP.otherMode.c2_m2a == 0 && gDP.otherMode.c2_m2b == 1) { @@ -552,8 +540,7 @@ void GraphicsDrawer::_setBlendMode() const return; } memFactorSource = 0; - } - else if (gDP.otherMode.c1_m2a == 1) { + } else if (gDP.otherMode.c1_m2a == 1) { memFactorSource = 1; } if (gDP.otherMode.c1_m2a == 0 && gDP.otherMode.c1_m2b == 1) { @@ -641,6 +628,56 @@ void GraphicsDrawer::_setBlendMode() const } } +void GraphicsDrawer::_dualSourceBlending() const +{ + if (gDP.otherMode.cycleType < G_CYC_COPY) { + BlendParam srcFactor = blend::ONE; + BlendParam dstFactor = blend::SRC1_COLOR; + BlendParam srcFactorAlpha = blend::ONE; + BlendParam dstFactorAlpha = blend::SRC1_ALPHA; + if (gDP.otherMode.forceBlender != 0) { + if (gDP.otherMode.cycleType == G_CYC_2CYCLE) { + if (gDP.otherMode.c2_m2a != 1 && gDP.otherMode.c2_m2b == 1) { + srcFactor = blend::DST_ALPHA; + } + if (gDP.otherMode.c2_m2a == 1 && gDP.otherMode.c2_m2b == 1) { + dstFactor = blend::DST_ALPHA; + } + } else { + if (gDP.otherMode.c1_m2a != 1 && gDP.otherMode.c1_m2b == 1) { + srcFactor = blend::DST_ALPHA; + } + if (gDP.otherMode.c1_m2a == 1 && gDP.otherMode.c2_m2b == 1) { + dstFactor = blend::DST_ALPHA; + } + } + } else if ((config.generalEmulation.hacks & hack_blastCorps) != 0 && + gSP.texture.on == 0 && currentCombiner()->usesTexture()) { // Blast Corps + srcFactor = blend::ZERO; + dstFactor = blend::ONE; + } + gfxContext.enable(enable::BLEND, true); + gfxContext.setBlendingSeparate(srcFactor, dstFactor, srcFactorAlpha, dstFactorAlpha); + } else { + gfxContext.enable(enable::BLEND, false); + } +} + +void GraphicsDrawer::setBlendMode(bool _forceLegacyBlending) const +{ + if (_forceLegacyBlending || config.generalEmulation.enableLegacyBlending != 0) { + _legacyBlending(); + return; + } + + if (Context::DualSourceBlending && !isTexrectDrawerMode()) { + _dualSourceBlending(); + return; + } + + _ordinaryBlending(); +} + void GraphicsDrawer::_updateTextures() const { //For some reason updating the texture cache on the first frame of LOZ:OOT causes a nullptr Pointer exception... @@ -685,7 +722,7 @@ void GraphicsDrawer::_updateStates(DrawingState _drawingState) const } if ((gDP.changed & (CHANGED_RENDERMODE | CHANGED_CYCLETYPE))) { - _setBlendMode(); + setBlendMode(); gDP.changed &= ~(CHANGED_RENDERMODE | CHANGED_CYCLETYPE); } @@ -1053,7 +1090,7 @@ bool texturedRectShadowMap(const GraphicsDrawer::TexturedRectParams &) pCurrentBuffer->m_pDepthBuffer->activateDepthBufferTexture(pCurrentBuffer); CombinerInfo::get().setDepthFogCombiner(); // DepthFogCombiner does not support shader blending. - _legacySetBlendMode(); + dwnd().getDrawer().setBlendMode(true); return false; } } diff --git a/GLideN64/src/GraphicsDrawer.h b/GLideN64/src/GraphicsDrawer.h index 67e339c..75e8f30 100644 --- a/GLideN64/src/GraphicsDrawer.h +++ b/GLideN64/src/GraphicsDrawer.h @@ -158,6 +158,8 @@ public: void setBackgroundDrawingMode(bool _mode) { m_bBGMode = _mode; } + void setBlendMode(bool _forceLegacyBlending = false) const; + private: friend class DisplayWindow; friend TexrectDrawer; @@ -173,8 +175,9 @@ private: void _setSpecialTexrect() const; - void _setBlendMode() const; - bool _setUnsupportedBlendMode() const; + void _legacyBlending() const; + void _ordinaryBlending() const; + void _dualSourceBlending() const; void _updateCullFace() const; void _updateViewport() const; void _updateScreenCoordsViewport(const FrameBuffer * _pBuffer = nullptr) const; diff --git a/GLideN64/src/RSP_LoadMatrixX86.cpp b/GLideN64/src/RSP_LoadMatrixX86.cpp index b38ad17..2ee25ec 100644 --- a/GLideN64/src/RSP_LoadMatrixX86.cpp +++ b/GLideN64/src/RSP_LoadMatrixX86.cpp @@ -1,3 +1,4 @@ +#include #include "RSP.h" #include "GBI.h" @@ -89,7 +90,7 @@ LoadLoop: " loop LoadLoop" "\n\t" ".att_syntax prefix" "\n\t" : /* no output */ - : "f"(recip), "S"((int)RDRAM+address), "D"(mtx), "c"(4) + : "f"(recip), "S"((intptr_t)RDRAM+address), "D"(mtx), "c"(4) : "memory" ); #endif // WIN32_ASM } diff --git a/GLideN64/src/TexrectDrawer.cpp b/GLideN64/src/TexrectDrawer.cpp index 3d75b49..e833523 100644 --- a/GLideN64/src/TexrectDrawer.cpp +++ b/GLideN64/src/TexrectDrawer.cpp @@ -350,7 +350,7 @@ bool TexrectDrawer::draw() ValueKeeper scissor(gDP.scissor, m_scissor); DisplayWindow & wnd = dwnd(); GraphicsDrawer & drawer = wnd.getDrawer(); - drawer._setBlendMode(); + drawer.setBlendMode(); gDP.changed |= CHANGED_RENDERMODE; // Force update of depth compare parameters drawer._updateDepthCompare();