diff --git a/projects/msvc12/GLideN64.vcxproj b/projects/msvc12/GLideN64.vcxproj
index 7ac3520e..68982662 100644
--- a/projects/msvc12/GLideN64.vcxproj
+++ b/projects/msvc12/GLideN64.vcxproj
@@ -302,8 +302,11 @@
+
+
+
@@ -439,8 +442,11 @@
+
+
+
diff --git a/projects/msvc12/GLideN64.vcxproj.filters b/projects/msvc12/GLideN64.vcxproj.filters
index 0b885174..7f6831b6 100644
--- a/projects/msvc12/GLideN64.vcxproj.filters
+++ b/projects/msvc12/GLideN64.vcxproj.filters
@@ -320,6 +320,15 @@
Source Files\Graphics\OpenGL
+
+ Source Files\Graphics\OpenGL\GLSL
+
+
+ Source Files\Graphics\OpenGL\GLSL
+
+
+ Source Files\Graphics\OpenGL\GLSL
+
@@ -583,5 +592,14 @@
Header Files\Graphics\OpenGL
+
+ Header Files\Graphics\OpenGL\GLSL
+
+
+ Header Files\Graphics\OpenGL\GLSL
+
+
+ Header Files\Graphics\OpenGL\GLSL
+
\ No newline at end of file
diff --git a/src/Graphics/CombinerProgram.h b/src/Graphics/CombinerProgram.h
index 443efae1..d9d702eb 100644
--- a/src/Graphics/CombinerProgram.h
+++ b/src/Graphics/CombinerProgram.h
@@ -10,6 +10,17 @@ namespace graphics {
virtual void activate() = 0;
virtual void update(bool _force) = 0;
virtual CombinerKey getKey() const = 0;
+ virtual bool usesTexture() const = 0;
+ virtual bool usesTile(u32 _t) const = 0;
+ virtual bool usesShade() const = 0;
+ virtual bool usesLOD() const = 0;
+
+ // TODO implement
+ void disableBlending() {}
+ void updateFrameBufferInfo(bool _bForce = false) {}
+
+ friend std::ostream & operator<< (std::ostream & _os, const CombinerProgram & _combiner);
+ friend std::istream & operator>> (std::istream & _os, CombinerProgram & _combiner);
};
}
diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerInputs.cpp b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerInputs.cpp
new file mode 100644
index 00000000..6407513b
--- /dev/null
+++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerInputs.cpp
@@ -0,0 +1,46 @@
+#include
+#include "glsl_CombinerInputs.h"
+
+using namespace glsl;
+
+bool CombinerInputs::usesTile(u32 _t) const
+{
+ if (_t == 0)
+ return (m_inputs & ((1 << TEXEL0) | (1 << TEXEL0_ALPHA))) != 0;
+ return (m_inputs & ((1 << TEXEL1) | (1 << TEXEL1_ALPHA))) != 0;
+}
+
+bool CombinerInputs::usesTexture() const
+{
+ return (m_inputs & ((1 << TEXEL1) | (1 << TEXEL1_ALPHA) | (1 << TEXEL0) | (1 << TEXEL0_ALPHA))) != 0;
+}
+
+bool CombinerInputs::usesLOD() const
+{
+ return (m_inputs & (1 << LOD_FRACTION)) != 0;
+}
+
+bool CombinerInputs::usesNoise() const
+{
+ return (m_inputs & (1 << NOISE)) != 0;
+}
+
+bool CombinerInputs::usesShade() const
+{
+ return (m_inputs & ((1 << SHADE) | (1 << SHADE_ALPHA))) != 0;
+}
+
+bool CombinerInputs::usesShadeColor() const
+{
+ return (m_inputs & (1 << SHADE)) != 0;
+}
+
+bool CombinerInputs::usesHwLighting() const
+{
+ return (m_inputs & (1 << HW_LIGHT)) != 0;
+}
+
+void CombinerInputs::addInput(int _input)
+{
+ m_inputs |= 1 << _input;
+}
diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerInputs.h b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerInputs.h
new file mode 100644
index 00000000..9850c9b3
--- /dev/null
+++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerInputs.h
@@ -0,0 +1,31 @@
+#pragma once
+#include
+
+namespace glsl {
+
+ class CombinerInputs
+ {
+ public:
+ explicit CombinerInputs(int _inputs) : m_inputs(_inputs) {}
+
+ bool usesTile(u32 _t) const;
+
+ bool usesTexture() const;
+
+ bool usesLOD() const;
+
+ bool usesNoise() const;
+
+ bool usesShade() const;
+
+ bool usesShadeColor() const;
+
+ bool usesHwLighting() const;
+
+ void addInput(int _input);
+
+ private:
+ int m_inputs;
+ };
+
+}
diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp
index c2aec594..dc88bd72 100644
--- a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp
+++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp
@@ -2,8 +2,11 @@
#include
#include
#include "glsl_Utils.h"
+#include "glsl_NoiseTexture.h"
+#include "glsl_CombinerInputs.h"
#include "glsl_CombinerProgramImpl.h"
#include "glsl_CombinerProgramBuilder.h"
+#include "glsl_CombinerProgramUniformFactory.h"
using namespace glsl;
@@ -178,9 +181,9 @@ int _compileCombiner(const CombinerStage & _stage, const char** _Input, std::str
class VertexShaderHeader : public ShaderPart
{
public:
- VertexShaderHeader(const opengl::GLInfo & _version)
+ VertexShaderHeader(const opengl::GLInfo & _glinfo)
{
- if (_version.isGLES2) {
+ if (_glinfo.isGLES2) {
m_part = "#version 100 \n";
m_part +=
"#if (__VERSION__ > 120) \n"
@@ -192,15 +195,15 @@ public:
"#endif // __VERSION \n"
;
}
- else if (_version.isGLESX) {
+ else if (_glinfo.isGLESX) {
std::stringstream ss;
- ss << "#version " << _version.majorVersion << _version.minorVersion << "0 es " << std::endl;
+ ss << "#version " << _glinfo.majorVersion << _glinfo.minorVersion << "0 es " << std::endl;
ss << "# define IN in" << std::endl << "# define OUT out" << std::endl;
m_part = ss.str();
}
else {
std::stringstream ss;
- ss << "#version " << _version.majorVersion << _version.minorVersion << "0 core " << std::endl;
+ ss << "#version " << _glinfo.majorVersion << _glinfo.minorVersion << "0 core " << std::endl;
ss << "# define IN in" << std::endl << "# define OUT out" << std::endl;
m_part = ss.str();
}
@@ -210,7 +213,7 @@ public:
class VertexShaderTexturedTriangle : public ShaderPart
{
public:
- VertexShaderTexturedTriangle(const opengl::GLInfo & _version)
+ VertexShaderTexturedTriangle(const opengl::GLInfo & _glinfo)
{
m_part =
"IN highp vec4 aPosition; \n"
@@ -276,7 +279,7 @@ public:
" vShadeColor.a = clamp(fp, 0.0, 1.0); \n"
" } \n"
;
- if (!_version.isGLESX) {
+ if (!_glinfo.isGLESX) {
m_part +=
" gl_ClipDistance[0] = gl_Position.w - gl_Position.z; \n"
;
@@ -290,7 +293,7 @@ public:
class VertexShaderTriangle : public ShaderPart
{
public:
- VertexShaderTriangle(const opengl::GLInfo & _version)
+ VertexShaderTriangle(const opengl::GLInfo & _glinfo)
{
m_part =
"IN highp vec4 aPosition; \n"
@@ -329,7 +332,7 @@ public:
" vShadeColor.a = clamp(fp, 0.0, 1.0); \n"
" } \n"
;
- if (!_version.isGLESX) {
+ if (!_glinfo.isGLESX) {
m_part +=
" gl_ClipDistance[0] = gl_Position.w - gl_Position.z; \n"
;
@@ -343,7 +346,7 @@ public:
class VertexShaderTexturedRect : public ShaderPart
{
public:
- VertexShaderTexturedRect(const opengl::GLInfo & _version)
+ VertexShaderTexturedRect(const opengl::GLInfo & _glinfo)
{
m_part =
"IN highp vec4 aRectPosition; \n"
@@ -361,7 +364,7 @@ public:
" vTexCoord0 = aTexCoord0; \n"
" vTexCoord1 = aTexCoord1; \n"
;
- if (!_version.isGLESX) {
+ if (!_glinfo.isGLESX) {
m_part +=
" gl_ClipDistance[0] = gl_Position.w - gl_Position.z; \n"
;
@@ -375,7 +378,7 @@ public:
class VertexShaderRect : public ShaderPart
{
public:
- VertexShaderRect(const opengl::GLInfo & _version)
+ VertexShaderRect(const opengl::GLInfo & _glinfo)
{
m_part =
"IN highp vec4 aRectPosition; \n"
@@ -387,7 +390,7 @@ public:
" gl_Position = aRectPosition; \n"
" vShadeColor = aRectColor; \n"
;
- if (!_version.isGLESX) {
+ if (!_glinfo.isGLESX) {
m_part +=
" gl_ClipDistance[0] = gl_Position.w - gl_Position.z; \n"
;
@@ -401,9 +404,9 @@ public:
class FragmentShaderHeader : public ShaderPart
{
public:
- FragmentShaderHeader(const opengl::GLInfo & _version)
+ FragmentShaderHeader(const opengl::GLInfo & _glinfo)
{
- if (_version.isGLES2) {
+ if (_glinfo.isGLES2) {
m_part = "#version 100 \n";
m_part += "#extension GL_EXT_shader_texture_lod : enable \n";
m_part += "#extension GL_OES_standard_derivatives : enable \n";
@@ -417,14 +420,14 @@ public:
"#endif // __VERSION __ \n"
;
}
- else if (_version.isGLESX) {
+ else if (_glinfo.isGLESX) {
std::stringstream ss;
- ss << "#version " << _version.majorVersion << _version.minorVersion << "0 es " << std::endl;
+ ss << "#version " << _glinfo.majorVersion << _glinfo.minorVersion << "0 es " << std::endl;
ss << "# define IN in" << std::endl << "# define OUT out" << std::endl;
m_part = ss.str();
} else {
std::stringstream ss;
- ss << "#version " << _version.majorVersion << _version.minorVersion << "0 core " << std::endl;
+ ss << "#version " << _glinfo.majorVersion << _glinfo.minorVersion << "0 core " << std::endl;
ss << "# define IN in" << std::endl << "# define OUT out" << std::endl;
m_part = ss.str();
}
@@ -434,9 +437,9 @@ public:
class ShaderBlender1 : public ShaderPart
{
public:
- ShaderBlender1(const opengl::GLInfo & _version)
+ ShaderBlender1(const opengl::GLInfo & _glinfo)
{
- if (_version.isGLES2) {
+ if (_glinfo.isGLES2) {
m_part =
" if (uForceBlendCycle1 != 0) { \n"
" muxPM[0] = clampedColor; \n"
@@ -500,9 +503,9 @@ public:
class ShaderBlender2 : public ShaderPart
{
public:
- ShaderBlender2(const opengl::GLInfo & _version)
+ ShaderBlender2(const opengl::GLInfo & _glinfo)
{
- if (_version.isGLES2) {
+ if (_glinfo.isGLES2) {
m_part =
" if (uForceBlendCycle2 != 0) { \n"
" muxPM[0] = clampedColor; \n"
@@ -689,9 +692,9 @@ public:
class ShaderCallDither : public ShaderPart
{
public:
- ShaderCallDither(const opengl::GLInfo & _version)
+ ShaderCallDither(const opengl::GLInfo & _glinfo)
{
- if (!_version.isGLES2 && config.generalEmulation.enableNoise != 0) {
+ if (!_glinfo.isGLES2 && config.generalEmulation.enableNoise != 0) {
m_part =
" if (uColorDitherMode == 2) colorNoiseDither(snoise(), clampedColor.rgb); \n"
" if (uAlphaDitherMode == 2) alphaNoiseDither(snoise(), clampedColor.a); \n"
@@ -703,7 +706,7 @@ public:
class ShaderFragmentGlobalVariablesTex : public ShaderPart
{
public:
- ShaderFragmentGlobalVariablesTex(const opengl::GLInfo & _version)
+ ShaderFragmentGlobalVariablesTex(const opengl::GLInfo & _glinfo)
{
m_part =
"uniform sampler2D uTex0; \n"
@@ -738,7 +741,7 @@ public:
;
}
- if (!_version.isGLES2) {
+ if (!_glinfo.isGLES2) {
m_part +=
"uniform sampler2D uDepthTex; \n"
"uniform lowp int uAlphaDitherMode; \n"
@@ -746,7 +749,7 @@ public:
"uniform lowp int uRenderTarget; \n"
"uniform mediump vec2 uDepthScale; \n"
;
- if (_version.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) {
+ if (_glinfo.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) {
m_part +=
"uniform lowp int uEnableDepthCompare; \n"
;
@@ -759,9 +762,9 @@ public:
if (config.video.multisampling > 0) {
m_part +=
- "uniform lowp ivec2 uMSTexEnabled; \n";
- "uniform lowp sampler2DMS uMSTex0; \n";
- "uniform lowp sampler2DMS uMSTex1; \n";
+ "uniform lowp ivec2 uMSTexEnabled; \n"
+ "uniform lowp sampler2DMS uMSTex0; \n"
+ "uniform lowp sampler2DMS uMSTex1; \n"
;
}
@@ -779,7 +782,7 @@ public:
class ShaderFragmentGlobalVariablesNotex : public ShaderPart
{
public:
- ShaderFragmentGlobalVariablesNotex(const opengl::GLInfo & _version)
+ ShaderFragmentGlobalVariablesNotex(const opengl::GLInfo & _glinfo)
{
m_part =
"uniform lowp vec4 uFogColor; \n"
@@ -812,7 +815,7 @@ public:
;
}
- if (!_version.isGLES2) {
+ if (!_glinfo.isGLES2) {
m_part +=
"uniform sampler2D uDepthTex; \n"
"uniform lowp int uAlphaDitherMode; \n"
@@ -820,7 +823,7 @@ public:
"uniform lowp int uRenderTarget; \n"
"uniform mediump vec2 uDepthScale; \n"
;
- if (_version.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) {
+ if (_glinfo.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) {
m_part +=
"uniform lowp int uEnableDepthCompare; \n"
;
@@ -841,7 +844,7 @@ public:
class ShaderFragmentHeaderNoise : public ShaderPart
{
public:
- ShaderFragmentHeaderNoise(const opengl::GLInfo & _version)
+ ShaderFragmentHeaderNoise(const opengl::GLInfo & _glinfo)
{
m_part =
"lowp float snoise();\n";
@@ -852,9 +855,9 @@ public:
class ShaderFragmentHeaderWriteDepth : public ShaderPart
{
public:
- ShaderFragmentHeaderWriteDepth(const opengl::GLInfo & _version)
+ ShaderFragmentHeaderWriteDepth(const opengl::GLInfo & _glinfo)
{
- if (!_version.isGLES2) {
+ if (!_glinfo.isGLES2) {
m_part =
"void writeDepth();\n";
;
@@ -865,7 +868,7 @@ public:
class ShaderFragmentHeaderCalcLight : public ShaderPart
{
public:
- ShaderFragmentHeaderCalcLight(const opengl::GLInfo & _version)
+ ShaderFragmentHeaderCalcLight(const opengl::GLInfo & _glinfo)
{
m_part =
"void calc_light(in lowp float fLights, in lowp vec3 input_color, out lowp vec3 output_color);\n";
@@ -876,7 +879,7 @@ public:
class ShaderFragmentHeaderMipMap : public ShaderPart
{
public:
- ShaderFragmentHeaderMipMap(const opengl::GLInfo & _version)
+ ShaderFragmentHeaderMipMap(const opengl::GLInfo & _glinfo)
{
m_part =
"mediump float mipmap(out lowp vec4 readtex0, out lowp vec4 readtex1);\n";
@@ -887,9 +890,9 @@ public:
class ShaderFragmentHeaderReadMSTex : public ShaderPart
{
public:
- ShaderFragmentHeaderReadMSTex(const opengl::GLInfo & _version)
+ ShaderFragmentHeaderReadMSTex(const opengl::GLInfo & _glinfo)
{
- if (!_version.isGLES2 && config.video.multisampling > 0) {
+ if (!_glinfo.isGLES2 && config.video.multisampling > 0) {
m_part =
"lowp vec4 readTexMS(in lowp sampler2DMS mstex, in mediump vec2 texCoord, in lowp int fbMonochrome, in lowp int fbFixedAlpha);\n";
;
@@ -900,9 +903,9 @@ public:
class ShaderFragmentHeaderDither : public ShaderPart
{
public:
- ShaderFragmentHeaderDither(const opengl::GLInfo & _version)
+ ShaderFragmentHeaderDither(const opengl::GLInfo & _glinfo)
{
- if (!_version.isGLES2 && config.generalEmulation.enableNoise != 0) {
+ if (!_glinfo.isGLES2 && config.generalEmulation.enableNoise != 0) {
m_part =
"void colorNoiseDither(in lowp float _noise, inout lowp vec3 _color);\n"
"void alphaNoiseDither(in lowp float _noise, inout lowp float _alpha);\n";
@@ -914,9 +917,9 @@ public:
class ShaderFragmentHeaderDepthCompare : public ShaderPart
{
public:
- ShaderFragmentHeaderDepthCompare(const opengl::GLInfo & _version)
+ ShaderFragmentHeaderDepthCompare(const opengl::GLInfo & _glinfo)
{
- if (_version.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) {
+ if (_glinfo.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) {
m_part =
"bool depth_compare();\n"
"bool depth_render(highp float Z);\n";
@@ -928,9 +931,9 @@ public:
class ShaderFragmentHeaderReadTex : public ShaderPart
{
public:
- ShaderFragmentHeaderReadTex (const opengl::GLInfo & _version)
+ ShaderFragmentHeaderReadTex (const opengl::GLInfo & _glinfo)
{
- if (!_version.isGLES2) {
+ if (!_glinfo.isGLES2) {
if (config.texture.bilinearMode == BILINEAR_3POINT) {
m_part =
"uniform lowp int uTextureFilterMode; \n"
@@ -977,13 +980,13 @@ public:
class ShaderFragmentMain : public ShaderPart
{
public:
- ShaderFragmentMain(const opengl::GLInfo & _version)
+ ShaderFragmentMain(const opengl::GLInfo & _glinfo)
{
m_part =
"void main() \n"
"{ \n"
;
- if (!_version.isGLES2) {
+ if (!_glinfo.isGLES2) {
m_part +=
" writeDepth(); \n"
;
@@ -999,13 +1002,13 @@ public:
class ShaderFragmentMain2Cycle : public ShaderPart
{
public:
- ShaderFragmentMain2Cycle(const opengl::GLInfo & _version)
+ ShaderFragmentMain2Cycle(const opengl::GLInfo & _glinfo)
{
m_part =
"void main() \n"
"{ \n"
;
- if (!_version.isGLES2) {
+ if (!_glinfo.isGLES2) {
m_part +=
" writeDepth(); \n"
;
@@ -1021,7 +1024,7 @@ public:
class ShaderFragmentBlendMux : public ShaderPart
{
public:
- ShaderFragmentBlendMux(const opengl::GLInfo & _version)
+ ShaderFragmentBlendMux(const opengl::GLInfo & _glinfo)
{
if (config.generalEmulation.enableLegacyBlending == 0) {
m_part =
@@ -1036,7 +1039,7 @@ public:
class ShaderFragmentReadTexMipmap : public ShaderPart
{
public:
- ShaderFragmentReadTexMipmap(const opengl::GLInfo & _version)
+ ShaderFragmentReadTexMipmap(const opengl::GLInfo & _glinfo)
{
m_part =
" lowp vec4 readtex0, readtex1; \n"
@@ -1048,26 +1051,26 @@ public:
class ShaderFragmentReadTex0 : public ShaderPart
{
public:
- ShaderFragmentReadTex0(const opengl::GLInfo & _version)
+ ShaderFragmentReadTex0(const opengl::GLInfo & _glinfo)
{
- if (_version.isGLES2) {
+ if (_glinfo.isGLES2) {
+ m_part =
+ " nCurrentTile = 0; \n"
+ " lowp vec4 readtex0 = readTex(uTex0, vTexCoord0, uFbMonochrome[0], uFbFixedAlpha[0]); \n"
+ ;
+ } else {
if (config.video.multisampling > 0) {
m_part =
" lowp vec4 readtex0; \n"
" if (uMSTexEnabled[0] == 0) READ_TEX(readtex0, uTex0, vTexCoord0, uFbMonochrome[0], uFbFixedAlpha[0]) \n"
" else readtex0 = readTexMS(uMSTex0, vTexCoord0, uFbMonochrome[0], uFbFixedAlpha[0]); \n"
- ;
+ ;
} else {
m_part =
" lowp vec4 readtex0; \n"
" READ_TEX(readtex0, uTex0, vTexCoord0, uFbMonochrome[0], uFbFixedAlpha[0]); \n"
- ;
+ ;
}
- } else {
- m_part =
- " nCurrentTile = 0; \n"
- " lowp vec4 readtex0 = readTex(uTex0, vTexCoord0, uFbMonochrome[0], uFbFixedAlpha[0]); \n"
- ;
}
}
};
@@ -1075,38 +1078,36 @@ public:
class ShaderFragmentReadTex1 : public ShaderPart
{
public:
- ShaderFragmentReadTex1(const opengl::GLInfo & _version)
+ ShaderFragmentReadTex1(const opengl::GLInfo & _glinfo)
{
- if (_version.isGLES2) {
+ if (_glinfo.isGLES2) {
+ m_part =
+ " nCurrentTile = 1; \n"
+ " lowp vec4 readtex1 = readTex(uTex1, vTexCoord1, uFbMonochrome[1], uFbFixedAlpha[1]); \n"
+ ;
+ } else {
if (config.video.multisampling > 0) {
m_part =
" lowp vec4 readtex1; \n"
" if (uMSTexEnabled[1] == 0) READ_TEX(readtex1, uTex1, vTexCoord1, uFbMonochrome[1], uFbFixedAlpha[1]) \n"
" else readtex1 = readTexMS(uMSTex1, vTexCoord1, uFbMonochrome[1], uFbFixedAlpha[1]); \n"
- ;
- }
- else {
+ ;
+ } else {
m_part =
" lowp vec4 readtex1; \n"
" READ_TEX(readtex1, uTex1, vTexCoord1, uFbMonochrome[1], uFbFixedAlpha[1]); \n"
- ;
+ ;
}
}
- else {
- m_part =
- " nCurrentTile = 1; \n"
- " lowp vec4 readtex1 = readTex(uTex1, vTexCoord1, uFbMonochrome[1], uFbFixedAlpha[1]); \n"
- ;
- }
}
};
class ShaderFragmentCallN64Depth : public ShaderPart
{
public:
- ShaderFragmentCallN64Depth(const opengl::GLInfo & _version)
+ ShaderFragmentCallN64Depth(const opengl::GLInfo & _glinfo)
{
- if (!_version.isGLES2 && _version.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) {
+ if (!_glinfo.isGLES2 && _glinfo.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) {
m_part =
" if (uRenderTarget != 0) { if (!depth_render(fragColor.r)) discard; } \n"
" else if (!depth_compare()) discard; \n"
@@ -1118,9 +1119,9 @@ public:
class ShaderFragmentRenderTarget : public ShaderPart
{
public:
- ShaderFragmentRenderTarget(const opengl::GLInfo & _version)
+ ShaderFragmentRenderTarget(const opengl::GLInfo & _glinfo)
{
- if (!_version.isGLES2 && config.generalEmulation.enableFragmentDepthWrite != 0) {
+ if (!_glinfo.isGLES2 && config.generalEmulation.enableFragmentDepthWrite != 0) {
m_part =
" if (uRenderTarget != 0) { \n"
" if (uRenderTarget > 1) { \n"
@@ -1137,7 +1138,7 @@ public:
class ShaderNoise : public ShaderPart
{
public:
- ShaderNoise(const opengl::GLInfo & _version)
+ ShaderNoise(const opengl::GLInfo & _glinfo)
{
if (config.generalEmulation.enableNoise == 0) {
// Dummy noise
@@ -1148,7 +1149,7 @@ public:
"} \n"
;
} else {
- if (_version.isGLES2) {
+ if (_glinfo.isGLES2) {
m_part =
"uniform sampler2D uTexNoise; \n"
"lowp float snoise() \n"
@@ -1175,9 +1176,9 @@ public:
class ShaderDither : public ShaderPart
{
public:
- ShaderDither(const opengl::GLInfo & _version)
+ ShaderDither(const opengl::GLInfo & _glinfo)
{
- if (!_version.isGLES2 && config.generalEmulation.enableNoise != 0) {
+ if (!_glinfo.isGLES2 && config.generalEmulation.enableNoise != 0) {
m_part =
"void colorNoiseDither(in lowp float _noise, inout lowp vec3 _color) \n"
"{ \n"
@@ -1203,9 +1204,9 @@ public:
class ShaderWriteDepth : public ShaderPart
{
public:
- ShaderWriteDepth(const opengl::GLInfo & _version)
+ ShaderWriteDepth(const opengl::GLInfo & _glinfo)
{
- if (!_version.isGLES2) {
+ if (!_glinfo.isGLES2) {
if (config.generalEmulation.enableFragmentDepthWrite == 0) {
// Dummy write depth
m_part =
@@ -1228,9 +1229,9 @@ public:
class ShaderMipmap : public ShaderPart
{
public:
- ShaderMipmap(const opengl::GLInfo & _version)
+ ShaderMipmap(const opengl::GLInfo & _glinfo)
{
- if (_version.isGLES2) {
+ if (_glinfo.isGLES2) {
if (config.generalEmulation.enableLOD == 0) {
// Fake mipmap
m_part =
@@ -1390,7 +1391,7 @@ public:
class ShaderCalcLight : public ShaderPart
{
public:
- ShaderCalcLight(const opengl::GLInfo & _version)
+ ShaderCalcLight(const opengl::GLInfo & _glinfo)
{
m_part =
"uniform mediump vec3 uLightDirection[8]; \n"
@@ -1415,9 +1416,9 @@ public:
class ShaderReadtex : public ShaderPart
{
public:
- ShaderReadtex(const opengl::GLInfo & _version)
+ ShaderReadtex(const opengl::GLInfo & _glinfo)
{
- if (_version.isGLES2) {
+ if (_glinfo.isGLES2) {
if (config.texture.bilinearMode == BILINEAR_3POINT) {
m_part =
"uniform mediump vec2 uTextureSize[2]; \n"
@@ -1502,10 +1503,10 @@ public:
class ShaderN64DepthCompare : public ShaderPart
{
public:
- ShaderN64DepthCompare(const opengl::GLInfo & _version)
+ ShaderN64DepthCompare(const opengl::GLInfo & _glinfo)
{
- if (_version.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) {
- m_part = _version.isGLESX
+ if (_glinfo.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) {
+ m_part = _glinfo.isGLESX
? "layout(binding = 2, rgba32f) highp uniform coherent image2D uDepthImage;\n"
: "layout(binding = 2, rg32f) highp uniform coherent image2D uDepthImage;\n"
;
@@ -1564,10 +1565,10 @@ public:
class ShaderN64DepthRender : public ShaderPart
{
public:
- ShaderN64DepthRender(const opengl::GLInfo & _version)
+ ShaderN64DepthRender(const opengl::GLInfo & _glinfo)
{
- if (_version.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) {
- m_part = _version.isGLESX
+ if (_glinfo.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0) {
+ m_part = _glinfo.isGLESX
? "layout(binding = 2, rgba32f) highp uniform coherent image2D uDepthImage;\n"
: "layout(binding = 2, rg32f) highp uniform coherent image2D uDepthImage;\n"
;
@@ -1645,7 +1646,7 @@ int CombinerProgramBuilder::compileCombiner(const CombinerKey & _key, Combiner &
_correctFirstStageParams(_alpha.stage[0]);
_correctFirstStageParams(_color.stage[0]);
}
- _strShader.append(" alpha1 = ");
+ ssShader << " alpha1 = ";
int nInputs = _compileCombiner(_alpha.stage[0], AlphaInput, ssShader);
// Simulate N64 color sign-extend.
if (combinedAlphaC(combine))
@@ -1655,7 +1656,7 @@ int CombinerProgramBuilder::compileCombiner(const CombinerKey & _key, Combiner &
m_alphaTest->write(ssShader);
- _strShader.append(" color1 = ");
+ ssShader << " color1 = ";
nInputs |= _compileCombiner(_color.stage[0], ColorInput, ssShader);
// Simulate N64 color sign-extend.
if (combinedColorC(combine))
@@ -1712,7 +1713,7 @@ int CombinerProgramBuilder::compileCombiner(const CombinerKey & _key, Combiner &
m_legacyBlender->write(ssShader);
}
- _strShader = ssShader.str();
+ _strShader = std::move(ssShader.str());
return nInputs;
}
@@ -1842,10 +1843,11 @@ graphics::CombinerProgram * CombinerProgramBuilder::buildCombinerProgram(Combine
glLinkProgram(program);
assert(Utils::checkProgramLinkStatus(program));
glDeleteShader(fragmentShader);
-// _locateUniforms();
+ UniformGroups uniforms;
+ m_uniformFactory->buildUniforms(program, combinerInputs, bIsRect, uniforms);
- return nullptr;
+ return new CombinerProgramImpl(program, combinerInputs, std::move(uniforms));
}
static
@@ -1864,9 +1866,9 @@ GLuint _createVertexShader(ShaderPart * _header, ShaderPart * _body)
return shader_object;
}
-CombinerProgramBuilder::CombinerProgramBuilder(const opengl::GLInfo & _version)
-: m_blender1(new ShaderBlender1(_version))
-, m_blender2(new ShaderBlender2(_version))
+CombinerProgramBuilder::CombinerProgramBuilder(const opengl::GLInfo & _glinfo)
+: m_blender1(new ShaderBlender1(_glinfo))
+, m_blender2(new ShaderBlender2(_glinfo))
, m_legacyBlender(new ShaderLegacyBlender)
, m_clamp(new ShaderClamp)
, m_signExtendColorC(new ShaderSignExtendColorC)
@@ -1874,44 +1876,47 @@ CombinerProgramBuilder::CombinerProgramBuilder(const opengl::GLInfo & _version)
, m_signExtendColorABD(new ShaderSignExtendColorABD)
, m_signExtendAlphaABD(new ShaderSignExtendAlphaABD)
, m_alphaTest(new ShaderAlphaTest)
-, m_callDither(new ShaderCallDither(_version))
-, m_vertexHeader(new VertexShaderHeader(_version))
-, m_vertexRect(new VertexShaderRect(_version))
-, m_vertexTexturedRect(new VertexShaderTexturedRect(_version))
-, m_vertexTriangle(new VertexShaderTriangle(_version))
-, m_vertexTexturedTriangle(new VertexShaderTexturedTriangle(_version))
-, m_fragmentHeader(new FragmentShaderHeader(_version))
-, m_fragmentGlobalVariablesTex(new ShaderFragmentGlobalVariablesTex(_version))
-, m_fragmentGlobalVariablesNotex(new ShaderFragmentGlobalVariablesNotex(_version))
-, m_fragmentHeaderNoise(new ShaderFragmentHeaderNoise(_version))
-, m_fragmentHeaderWriteDepth(new ShaderFragmentHeaderWriteDepth(_version))
-, m_fragmentHeaderCalcLight(new ShaderFragmentHeaderCalcLight(_version))
-, m_fragmentHeaderMipMap(new ShaderFragmentHeaderMipMap(_version))
-, m_fragmentHeaderReadMSTex(new ShaderFragmentHeaderReadMSTex(_version))
-, m_fragmentHeaderDither(new ShaderFragmentHeaderDither(_version))
-, m_fragmentHeaderDepthCompare(new ShaderFragmentHeaderDepthCompare(_version))
-, m_fragmentHeaderReadTex(new ShaderFragmentHeaderReadTex(_version))
-, m_fragmentMain(new ShaderFragmentMain(_version))
-, m_fragmentMain2Cycle(new ShaderFragmentMain2Cycle(_version))
-, m_fragmentBlendMux(new ShaderFragmentBlendMux(_version))
-, m_fragmentReadTex0(new ShaderFragmentReadTex0(_version))
-, m_fragmentReadTex1(new ShaderFragmentReadTex1(_version))
-, m_fragmentReadTexMipmap(new ShaderFragmentReadTexMipmap(_version))
-, m_fragmentCallN64Depth(new ShaderFragmentCallN64Depth(_version))
-, m_fragmentRenderTarget(new ShaderFragmentRenderTarget(_version))
-, m_shaderNoise(new ShaderNoise(_version))
-, m_shaderDither(new ShaderDither(_version))
-, m_shaderWriteDepth(new ShaderWriteDepth(_version))
-, m_shaderMipmap(new ShaderMipmap(_version))
-, m_shaderCalcLight(new ShaderCalcLight(_version))
-, m_shaderReadtex(new ShaderReadtex(_version))
-, m_shaderN64DepthCompare(new ShaderN64DepthCompare(_version))
-, m_shaderN64DepthRender(new ShaderN64DepthRender(_version))
+, m_callDither(new ShaderCallDither(_glinfo))
+, m_vertexHeader(new VertexShaderHeader(_glinfo))
+, m_vertexRect(new VertexShaderRect(_glinfo))
+, m_vertexTexturedRect(new VertexShaderTexturedRect(_glinfo))
+, m_vertexTriangle(new VertexShaderTriangle(_glinfo))
+, m_vertexTexturedTriangle(new VertexShaderTexturedTriangle(_glinfo))
+, m_fragmentHeader(new FragmentShaderHeader(_glinfo))
+, m_fragmentGlobalVariablesTex(new ShaderFragmentGlobalVariablesTex(_glinfo))
+, m_fragmentGlobalVariablesNotex(new ShaderFragmentGlobalVariablesNotex(_glinfo))
+, m_fragmentHeaderNoise(new ShaderFragmentHeaderNoise(_glinfo))
+, m_fragmentHeaderWriteDepth(new ShaderFragmentHeaderWriteDepth(_glinfo))
+, m_fragmentHeaderCalcLight(new ShaderFragmentHeaderCalcLight(_glinfo))
+, m_fragmentHeaderMipMap(new ShaderFragmentHeaderMipMap(_glinfo))
+, m_fragmentHeaderReadMSTex(new ShaderFragmentHeaderReadMSTex(_glinfo))
+, m_fragmentHeaderDither(new ShaderFragmentHeaderDither(_glinfo))
+, m_fragmentHeaderDepthCompare(new ShaderFragmentHeaderDepthCompare(_glinfo))
+, m_fragmentHeaderReadTex(new ShaderFragmentHeaderReadTex(_glinfo))
+, m_fragmentMain(new ShaderFragmentMain(_glinfo))
+, m_fragmentMain2Cycle(new ShaderFragmentMain2Cycle(_glinfo))
+, m_fragmentBlendMux(new ShaderFragmentBlendMux(_glinfo))
+, m_fragmentReadTex0(new ShaderFragmentReadTex0(_glinfo))
+, m_fragmentReadTex1(new ShaderFragmentReadTex1(_glinfo))
+, m_fragmentReadTexMipmap(new ShaderFragmentReadTexMipmap(_glinfo))
+, m_fragmentCallN64Depth(new ShaderFragmentCallN64Depth(_glinfo))
+, m_fragmentRenderTarget(new ShaderFragmentRenderTarget(_glinfo))
+, m_shaderNoise(new ShaderNoise(_glinfo))
+, m_shaderDither(new ShaderDither(_glinfo))
+, m_shaderWriteDepth(new ShaderWriteDepth(_glinfo))
+, m_shaderMipmap(new ShaderMipmap(_glinfo))
+, m_shaderCalcLight(new ShaderCalcLight(_glinfo))
+, m_shaderReadtex(new ShaderReadtex(_glinfo))
+, m_shaderN64DepthCompare(new ShaderN64DepthCompare(_glinfo))
+, m_shaderN64DepthRender(new ShaderN64DepthRender(_glinfo))
{
m_vertexShaderRect = _createVertexShader(m_vertexHeader.get(), m_vertexRect.get());
m_vertexShaderTriangle = _createVertexShader(m_vertexHeader.get(), m_vertexTriangle.get());
m_vertexShaderTexturedRect = _createVertexShader(m_vertexHeader.get(), m_vertexTexturedRect.get());
m_vertexShaderTexturedTriangle = _createVertexShader(m_vertexHeader.get(), m_vertexTexturedTriangle.get());
+ if (config.generalEmulation.enableNoise != 0)
+ m_noiseTexture.reset(new NoiseTexture);
+ m_uniformFactory.reset(new CombinerProgramUniformFactory(_glinfo, m_noiseTexture.get()));
}
CombinerProgramBuilder::~CombinerProgramBuilder()
diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.h b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.h
index 1625bc07..191f5ba4 100644
--- a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.h
+++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.h
@@ -4,10 +4,16 @@
#include
#include
#include
-#include
+
+namespace graphics {
+ class CombinerProgram;
+}
namespace glsl {
+ class NoiseTexture;
+ class CombinerProgramUniformFactory;
+
class ShaderPart
{
public:
@@ -23,7 +29,7 @@ namespace glsl {
class CombinerProgramBuilder
{
public:
- CombinerProgramBuilder(const opengl::GLInfo & _version);
+ CombinerProgramBuilder(const opengl::GLInfo & _glinfo);
~CombinerProgramBuilder();
graphics::CombinerProgram * buildCombinerProgram(Combiner & _color, Combiner & _alpha, const CombinerKey & _key);
@@ -77,6 +83,9 @@ namespace glsl {
ShaderPartPtr m_shaderN64DepthCompare;
ShaderPartPtr m_shaderN64DepthRender;
+ std::unique_ptr m_noiseTexture;
+ std::unique_ptr m_uniformFactory;
+
GLuint m_vertexShaderRect;
GLuint m_vertexShaderTriangle;
GLuint m_vertexShaderTexturedRect;
diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramImpl.cpp b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramImpl.cpp
index 91396d8b..e6782805 100644
--- a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramImpl.cpp
+++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramImpl.cpp
@@ -3,50 +3,11 @@
using namespace glsl;
-/*---------------CombinerInputs-------------*/
-
-bool CombinerInputs::usesTile(u32 _t) const
-{
- if (_t == 0)
- return (m_inputs & ((1 << TEXEL0) | (1 << TEXEL0_ALPHA))) != 0;
- return (m_inputs & ((1 << TEXEL1) | (1 << TEXEL1_ALPHA))) != 0;
-}
-
-bool CombinerInputs::usesTexture() const
-{
- return (m_inputs & ((1 << TEXEL1) | (1 << TEXEL1_ALPHA) | (1 << TEXEL0) | (1 << TEXEL0_ALPHA))) != 0;
-}
-
-bool CombinerInputs::usesLOD() const
-{
- return (m_inputs & (1 << LOD_FRACTION)) != 0;
-}
-
-bool CombinerInputs::usesShade() const
-{
- return (m_inputs & ((1 << SHADE) | (1 << SHADE_ALPHA))) != 0;
-}
-
-bool CombinerInputs::usesShadeColor() const
-{
- return (m_inputs & (1 << SHADE)) != 0;
-}
-
-bool CombinerInputs::usesHwLighting() const
-{
- return (m_inputs & (1 << HW_LIGHT)) != 0;
-}
-
-void CombinerInputs::addInput(int _input)
-{
- m_inputs |= 1 << _input;
-}
-
-
-/*---------------CombinerProgramImpl-------------*/
-
-
-CombinerProgramImpl::CombinerProgramImpl()
+CombinerProgramImpl::CombinerProgramImpl(GLuint _program, const CombinerInputs & _inputs, UniformGroups && _uniforms)
+: m_bNeedUpdate(true)
+, m_program(_program)
+, m_inputs(_inputs)
+, m_uniforms(std::move(_uniforms))
{
}
@@ -57,14 +18,51 @@ CombinerProgramImpl::~CombinerProgramImpl()
void CombinerProgramImpl::activate()
{
+ glUseProgram(m_program);
}
void CombinerProgramImpl::update(bool _force)
{
-
+ _force |= m_bNeedUpdate;
+ m_bNeedUpdate = false;
+ glUseProgram(m_program);
+ for (auto it = m_uniforms.begin(); it != m_uniforms.end(); ++it)
+ (*it)->update(_force);
}
CombinerKey CombinerProgramImpl::getKey() const
{
return CombinerKey();
}
+
+bool CombinerProgramImpl::usesTexture() const
+{
+ return m_inputs.usesTexture();
+}
+
+bool CombinerProgramImpl::usesTile(u32 _t) const {
+ return m_inputs.usesTile(_t);
+}
+
+bool CombinerProgramImpl::usesShade() const {
+ return m_inputs.usesShade();
+}
+
+bool CombinerProgramImpl::usesLOD() const {
+ return m_inputs.usesLOD();
+}
+
+namespace graphics {
+
+ // TODO implement
+ std::ostream & operator<< (std::ostream & _os, const CombinerProgram & _combiner)
+ {
+ return _os;
+ }
+
+ std::istream & operator>> (std::istream & _is, CombinerProgram & _combiner)
+ {
+ return _is;
+ }
+
+}
\ No newline at end of file
diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramImpl.h b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramImpl.h
index 43f8be86..7cf98518 100644
--- a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramImpl.h
+++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramImpl.h
@@ -1,40 +1,39 @@
#pragma once
+#include
+#include
#include
+#include "glsl_CombinerInputs.h"
namespace glsl {
- class CombinerInputs
- {
+ class UniformGroup {
public:
- explicit CombinerInputs(int _inputs) : m_inputs(_inputs) {}
-
- bool usesTile(u32 _t) const;
-
- bool usesTexture() const;
-
- bool usesLOD() const;
-
- bool usesShade() const;
-
- bool usesShadeColor() const;
-
- bool usesHwLighting() const;
-
- void addInput(int _input);
-
- private:
- int m_inputs;
+ virtual ~UniformGroup() {}
+ virtual void update(bool _force) = 0;
};
+ typedef std::vector< std::unique_ptr > UniformGroups;
+
class CombinerProgramImpl : public graphics::CombinerProgram
{
public:
- CombinerProgramImpl();
+ CombinerProgramImpl(GLuint _program, const CombinerInputs & _inputs, UniformGroups && _uniforms);
~CombinerProgramImpl();
void activate() override;
void update(bool _force) override;
CombinerKey getKey() const override;
+
+ bool usesTexture() const override;
+ bool usesTile(u32 _t) const override;
+ bool usesShade() const override;
+ bool usesLOD() const override;
+
+ private:
+ bool m_bNeedUpdate;
+ GLuint m_program;
+ CombinerInputs m_inputs;
+ UniformGroups m_uniforms;
};
}
diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp
new file mode 100644
index 00000000..276c09a5
--- /dev/null
+++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp
@@ -0,0 +1,861 @@
+#include
+#include "glsl_CombinerProgramUniformFactory.h"
+#include "glsl_NoiseTexture.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace glsl {
+
+/*---------------Uniform-------------*/
+
+struct iUniform {
+ GLint loc = -1;
+ int val = -999;
+ void set(int _val, bool _force) {
+ if (loc >= 0 && (_force || val != _val)) {
+ val = _val;
+ glUniform1i(loc, _val);
+ }
+ }
+};
+
+struct fUniform {
+ GLint loc = -1;
+ float val = -9999.9f;
+ void set(float _val, bool _force) {
+ if (loc >= 0 && (_force || val != _val)) {
+ val = _val;
+ glUniform1f(loc, _val);
+ }
+ }
+};
+
+struct fv2Uniform {
+ GLint loc = -1;
+ float val1 = -9999.9f, val2 = -9999.9f;
+ void set(float _val1, float _val2, bool _force) {
+ if (loc >= 0 && (_force || val1 != _val1 || val2 != _val2)) {
+ val1 = _val1;
+ val2 = _val2;
+ glUniform2f(loc, _val1, _val2);
+ }
+ }
+};
+
+struct fv3Uniform {
+ GLint loc = -1;
+ float val[3];
+ void set(float * _pVal, bool _force) {
+ const size_t szData = sizeof(float)* 3;
+ if (loc >= 0 && (_force || memcmp(val, _pVal, szData) != 0)) {
+ memcpy(val, _pVal, szData);
+ glUniform3fv(loc, 1, _pVal);
+ }
+ }
+};
+
+struct fv4Uniform {
+ GLint loc = -1;
+ float val[4];
+ void set(float * _pVal, bool _force) {
+ const size_t szData = sizeof(float)* 4;
+ if (loc >= 0 && (_force || memcmp(val, _pVal, szData) != 0)) {
+ memcpy(val, _pVal, szData);
+ glUniform4fv(loc, 1, _pVal);
+ }
+ }
+};
+
+struct iv2Uniform {
+ GLint loc = -1;
+ int val1 = -999, val2 = -999;
+ void set(int _val1, int _val2, bool _force) {
+ if (loc >= 0 && (_force || val1 != _val1 || val2 != _val2)) {
+ val1 = _val1;
+ val2 = _val2;
+ glUniform2i(loc, _val1, _val2);
+ }
+ }
+};
+
+struct i4Uniform {
+ GLint loc = -1;
+ int val0 = -999, val1 = -999, val2 = -999, val3 = -999;
+ void set(int _val0, int _val1, int _val2, int _val3, bool _force) {
+ if (loc < 0)
+ return;
+ if (_force || _val0 != val0 || _val1 != val1 || _val2 != val2 || _val3 != val3) {
+ val0 = _val0;
+ val1 = _val1;
+ val2 = _val2;
+ val3 = _val3;
+ glUniform4i(loc, val0, val1, val2, val3);
+ }
+ }
+};
+
+
+/*---------------UniformGroup-------------*/
+
+#define LocateUniform(A) \
+ A.loc = glGetUniformLocation(_program, #A);
+
+class UNoiseTex : public UniformGroup
+{
+public:
+ UNoiseTex(GLuint _program) {
+ LocateUniform(uTexNoise);
+ }
+
+ void update(bool _force) override
+ {
+ uTexNoise.set(g_noiseTexIndex, _force);
+ }
+
+private:
+ iUniform uTexNoise;
+};
+
+class UDepthTex : public UniformGroup
+{
+public:
+ UDepthTex(GLuint _program) {
+ LocateUniform(uDepthTex);
+ }
+
+ void update(bool _force) override
+ {
+ uDepthTex.set(g_depthTexIndex, _force);
+ }
+
+private:
+ iUniform uDepthTex;
+};
+
+class UTextures : public UniformGroup
+{
+public:
+ UTextures(GLuint _program) {
+ LocateUniform(uTex0);
+ LocateUniform(uTex1);
+ }
+
+ void update(bool _force) override
+ {
+ uTex0.set(0, _force);
+ uTex1.set(1, _force);
+ }
+
+private:
+ iUniform uTex0;
+ iUniform uTex1;
+};
+
+class UMSAATextures : public UniformGroup
+{
+public:
+ UMSAATextures(GLuint _program) {
+ LocateUniform(uMSTex0);
+ LocateUniform(uMSTex1);
+ LocateUniform(uMSAASamples);
+ LocateUniform(uMSAAScale);
+ }
+
+ void update(bool _force) override
+ {
+ uMSTex0.set(g_MSTex0Index + 0, _force);
+ uMSTex1.set(g_MSTex0Index + 1, _force);
+ uMSAASamples.set(config.video.multisampling, _force);
+ uMSAAScale.set(1.0f / (float)config.video.multisampling, _force);
+ }
+
+private:
+ iUniform uMSTex0;
+ iUniform uMSTex1;
+ iUniform uMSAASamples;
+ fUniform uMSAAScale;
+};
+
+class UFrameBufferInfo : public UniformGroup
+{
+public:
+ UFrameBufferInfo(GLuint _program) {
+ LocateUniform(uFbMonochrome);
+ LocateUniform(uFbFixedAlpha);
+ LocateUniform(uMSTexEnabled);
+ }
+
+ void update(bool _force) override
+ {
+ int nFbMonochromeMode0 = 0, nFbMonochromeMode1 = 0;
+ int nFbFixedAlpha0 = 0, nFbFixedAlpha1 = 0;
+ int nMSTex0Enabled = 0, nMSTex1Enabled = 0;
+ TextureCache & cache = textureCache();
+ if (cache.current[0] != nullptr && cache.current[0]->frameBufferTexture != CachedTexture::fbNone) {
+ if (cache.current[0]->size == G_IM_SIZ_8b) {
+ nFbMonochromeMode0 = 1;
+ if (gDP.otherMode.imageRead == 0)
+ nFbFixedAlpha0 = 1;
+ }
+ else if (gSP.textureTile[0]->size == G_IM_SIZ_16b && gSP.textureTile[0]->format == G_IM_FMT_IA)
+ nFbMonochromeMode0 = 2;
+ nMSTex0Enabled = cache.current[0]->frameBufferTexture == CachedTexture::fbMultiSample ? 1 : 0;
+ }
+ if (cache.current[1] != nullptr && cache.current[1]->frameBufferTexture != CachedTexture::fbNone) {
+ if (cache.current[1]->size == G_IM_SIZ_8b) {
+ nFbMonochromeMode1 = 1;
+ if (gDP.otherMode.imageRead == 0)
+ nFbFixedAlpha1 = 1;
+ }
+ else if (gSP.textureTile[1]->size == G_IM_SIZ_16b && gSP.textureTile[1]->format == G_IM_FMT_IA)
+ nFbMonochromeMode1 = 2;
+ nMSTex1Enabled = cache.current[1]->frameBufferTexture == CachedTexture::fbMultiSample ? 1 : 0;
+ }
+ uFbMonochrome.set(nFbMonochromeMode0, nFbMonochromeMode1, _force);
+ uFbFixedAlpha.set(nFbFixedAlpha0, nFbFixedAlpha1, _force);
+ uMSTexEnabled.set(nMSTex0Enabled, nMSTex1Enabled, _force);
+ gDP.changed &= ~CHANGED_FB_TEXTURE;
+ }
+
+private:
+ iv2Uniform uFbMonochrome;
+ iv2Uniform uFbFixedAlpha;
+ iv2Uniform uMSTexEnabled;
+};
+
+
+class UFog : public UniformGroup
+{
+public:
+ UFog(GLuint _program) {
+ LocateUniform(uFogUsage);
+ LocateUniform(uFogScale);
+ }
+
+ void update(bool _force) override
+ {
+ if (RSP.bLLE) {
+ uFogUsage.set(0, _force);
+ return;
+ }
+
+ int nFogUsage = ((gSP.geometryMode & G_FOG) != 0) ? 1 : 0;
+ if (!GBI.isTextureGen())
+ // F-Zero ucode seems to always use fog mode when fog is used in blender.
+ nFogUsage |= (gDP.otherMode.c1_m1a == 3 || gDP.otherMode.c1_m2a == 3) ? 1 : 0;
+ uFogUsage.set(nFogUsage, _force);
+ uFogScale.set((float)gSP.fog.multiplier / 256.0f, (float)gSP.fog.offset / 256.0f, _force);
+ }
+
+private:
+ iUniform uFogUsage;
+ fv2Uniform uFogScale;
+};
+
+class UBlendMode1Cycle : public UniformGroup
+{
+public:
+ UBlendMode1Cycle(GLuint _program) {
+ LocateUniform(uBlendMux1);
+ LocateUniform(uForceBlendCycle1);
+ }
+
+ void update(bool _force) override
+ {
+ uBlendMux1.set(gDP.otherMode.c1_m1a,
+ gDP.otherMode.c1_m1b,
+ gDP.otherMode.c1_m2a,
+ gDP.otherMode.c1_m2b,
+ _force);
+ int forceBlend1 = gDP.otherMode.forceBlender;
+
+ uForceBlendCycle1.set(forceBlend1, _force);
+ }
+
+private:
+ i4Uniform uBlendMux1;
+ iUniform uForceBlendCycle1;
+};
+
+class UBlendMode2Cycle : public UniformGroup
+{
+public:
+ UBlendMode2Cycle(GLuint _program) {
+ LocateUniform(uBlendMux1);
+ LocateUniform(uBlendMux2);
+ LocateUniform(uForceBlendCycle1);
+ LocateUniform(uForceBlendCycle2);
+ }
+
+ void update(bool _force) override
+ {
+ int forceBlend1 = 1;
+
+ uBlendMux1.set(gDP.otherMode.c1_m1a,
+ gDP.otherMode.c1_m1b,
+ gDP.otherMode.c1_m2a,
+ gDP.otherMode.c1_m2b,
+ _force);
+
+ int forceBlend2 = gDP.otherMode.forceBlender;
+
+ if (forceBlend2 != 0) {
+ uBlendMux2.set(gDP.otherMode.c2_m1a,
+ gDP.otherMode.c2_m1b,
+ gDP.otherMode.c2_m2a,
+ gDP.otherMode.c2_m2b,
+ _force);
+ }
+
+ uForceBlendCycle1.set(forceBlend1, _force);
+ uForceBlendCycle2.set(forceBlend2, _force);
+ }
+
+private:
+ i4Uniform uBlendMux1;
+ i4Uniform uBlendMux2;
+ iUniform uForceBlendCycle1;
+ iUniform uForceBlendCycle2;
+};
+
+class UDitherMode : public UniformGroup
+{
+public:
+ UDitherMode(GLuint _program, bool _usesNoise, NoiseTexture * _noiseTexture)
+ : m_usesNoise(m_usesNoise)
+ , m_noiseTexture(_noiseTexture)
+ {
+ LocateUniform(uAlphaCompareMode);
+ LocateUniform(uAlphaDitherMode);
+ LocateUniform(uColorDitherMode);
+ }
+ ~UDitherMode()
+ {
+ m_noiseTexture = nullptr;
+ }
+
+ void update(bool _force) override
+ {
+ if (gDP.otherMode.cycleType < G_CYC_COPY) {
+ uAlphaCompareMode.set(gDP.otherMode.alphaCompare, _force);
+ uAlphaDitherMode.set(gDP.otherMode.alphaDither, _force);
+ uColorDitherMode.set(gDP.otherMode.colorDither, _force);
+ }
+ else {
+ uAlphaCompareMode.set(0, _force);
+ uAlphaDitherMode.set(0, _force);
+ uColorDitherMode.set(0, _force);
+ }
+
+ bool updateNoiseTex = m_usesNoise;
+ updateNoiseTex |= (gDP.otherMode.cycleType < G_CYC_COPY) && (gDP.otherMode.colorDither == G_CD_NOISE || gDP.otherMode.alphaDither == G_AD_NOISE || gDP.otherMode.alphaCompare == G_AC_DITHER);
+ if (updateNoiseTex && m_noiseTexture != nullptr)
+ m_noiseTexture->update();
+ }
+
+private:
+ iUniform uAlphaCompareMode;
+ iUniform uAlphaDitherMode;
+ iUniform uColorDitherMode;
+ bool m_usesNoise;
+ NoiseTexture * m_noiseTexture;
+};
+
+class UScreenScale : public UniformGroup
+{
+public:
+ UScreenScale(GLuint _program) {
+ LocateUniform(uScreenScale);
+ }
+
+ void update(bool _force) override
+ {
+ if (config.frameBufferEmulation.nativeResFactor == 0)
+ // TODO fix me
+ //uScreenScale.set(video().getScaleX(), video().getScaleY(), _force);
+ uScreenScale.set(1.0f, 1.0f, _force);
+ else
+ uScreenScale.set(float(config.frameBufferEmulation.nativeResFactor), float(config.frameBufferEmulation.nativeResFactor), _force);
+ }
+
+private:
+ fv2Uniform uScreenScale;
+};
+
+class UMipmap1 : public UniformGroup
+{
+public:
+ UMipmap1(GLuint _program) {
+ LocateUniform(uMinLod);
+ LocateUniform(uMaxTile);
+ }
+
+ void update(bool _force) override
+ {
+ uMinLod.set(gDP.primColor.m, _force);
+ uMaxTile.set(gSP.texture.level, _force);
+ }
+
+private:
+ fUniform uMinLod;
+ iUniform uMaxTile;
+};
+
+class UMipmap2 : public UniformGroup
+{
+public:
+ UMipmap2(GLuint _program) {
+ LocateUniform(uEnableLod);
+ LocateUniform(uTextureDetail);
+ }
+
+ void update(bool _force) override
+ {
+ const int uCalcLOD = (gDP.otherMode.textureLOD == G_TL_LOD) ? 1 : 0;
+ uEnableLod.set(uCalcLOD, _force);
+ uTextureDetail.set(gDP.otherMode.textureDetail, _force);
+ }
+
+private:
+ iUniform uEnableLod;
+ iUniform uTextureDetail;
+};
+
+class UTexturePersp : public UniformGroup
+{
+public:
+ UTexturePersp(GLuint _program) {
+ LocateUniform(uTexturePersp);
+ }
+
+ void update(bool _force) override
+ {
+ const u32 texturePersp = (RSP.bLLE || GBI.isTexturePersp()) ? gDP.otherMode.texturePersp : 1U;
+ uTexturePersp.set(texturePersp, _force);
+ }
+
+private:
+ iUniform uTexturePersp;
+};
+
+class UTextureFilterMode : public UniformGroup
+{
+public:
+ UTextureFilterMode(GLuint _program) {
+ LocateUniform(uTextureFilterMode);
+ }
+
+ void update(bool _force) override
+ {
+ uTextureFilterMode.set(gDP.otherMode.textureFilter | (gSP.objRendermode&G_OBJRM_BILERP), _force);
+ }
+
+private:
+ iUniform uTextureFilterMode;
+};
+
+class UAlphaTestInfo : public UniformGroup
+{
+public:
+ UAlphaTestInfo(GLuint _program) {
+ LocateUniform(uEnableAlphaTest);
+ LocateUniform(uAlphaCvgSel);
+ LocateUniform(uCvgXAlpha);
+ LocateUniform(uAlphaTestValue);
+ }
+
+ void update(bool _force) override
+ {
+ if (gDP.otherMode.cycleType == G_CYC_FILL) {
+ uEnableAlphaTest.set(0, _force);
+ }
+ else if (gDP.otherMode.cycleType == G_CYC_COPY) {
+ if (gDP.otherMode.alphaCompare & G_AC_THRESHOLD) {
+ uEnableAlphaTest.set(1, _force);
+ uAlphaCvgSel.set(0, _force);
+ uAlphaTestValue.set(0.5f, _force);
+ }
+ else {
+ uEnableAlphaTest.set(0, _force);
+ }
+ }
+ else if ((gDP.otherMode.alphaCompare & G_AC_THRESHOLD) != 0) {
+ uEnableAlphaTest.set(1, _force);
+ uAlphaTestValue.set(gDP.blendColor.a, _force);
+ uAlphaCvgSel.set(gDP.otherMode.alphaCvgSel, _force);
+ }
+ else {
+ uEnableAlphaTest.set(0, _force);
+ }
+
+ uCvgXAlpha.set(gDP.otherMode.cvgXAlpha, _force);
+ }
+
+private:
+ iUniform uEnableAlphaTest;
+ iUniform uAlphaCvgSel;
+ iUniform uCvgXAlpha;
+ fUniform uAlphaTestValue;
+};
+
+class UDepthScale : public UniformGroup
+{
+public:
+ UDepthScale(GLuint _program) {
+ LocateUniform(uDepthScale);
+ }
+
+ void update(bool _force) override
+ {
+ if (RSP.bLLE)
+ uDepthScale.set(0.5f, 0.5f, _force);
+ else
+ uDepthScale.set(gSP.viewport.vscale[2], gSP.viewport.vtrans[2], _force);
+ }
+
+private:
+ fv2Uniform uDepthScale;
+};
+
+class UDepthInfo : public UniformGroup
+{
+public:
+ UDepthInfo(GLuint _program) {
+ LocateUniform(uEnableDepth);
+ LocateUniform(uEnableDepthCompare);
+ LocateUniform(uEnableDepthUpdate);
+ LocateUniform(uDepthMode);
+ LocateUniform(uDepthSource);
+ LocateUniform(uDeltaZ);
+ }
+
+ void update(bool _force) override
+ {
+ FrameBuffer * pBuffer = frameBufferList().getCurrent();
+ if (pBuffer == nullptr || pBuffer->m_pDepthBuffer == nullptr)
+ return;
+
+ const int nDepthEnabled = (gSP.geometryMode & G_ZBUFFER) > 0 ? 1 : 0;
+ uEnableDepth.set(nDepthEnabled, _force);
+ if (nDepthEnabled == 0) {
+ uEnableDepthCompare.set(0, _force);
+ uEnableDepthUpdate.set(0, _force);
+ }
+ else {
+ uEnableDepthCompare.set(gDP.otherMode.depthCompare, _force);
+ uEnableDepthUpdate.set(gDP.otherMode.depthUpdate, _force);
+ }
+ uDepthMode.set(gDP.otherMode.depthMode, _force);
+ uDepthSource.set(gDP.otherMode.depthSource, _force);
+ if (gDP.otherMode.depthSource == G_ZS_PRIM)
+ uDeltaZ.set(gDP.primDepth.deltaZ, _force);
+ }
+
+private:
+ iUniform uEnableDepth;
+ iUniform uEnableDepthCompare;
+ iUniform uEnableDepthUpdate;
+ iUniform uDepthMode;
+ iUniform uDepthSource;
+ fUniform uDeltaZ;
+};
+
+class URenderTarget : public UniformGroup
+{
+public:
+ URenderTarget(GLuint _program) {
+ LocateUniform(uRenderTarget);
+ }
+
+ void update(bool _force) override
+ {
+ int renderTarget = 0;
+ if (gDP.colorImage.address == gDP.depthImageAddress &&
+ (config.generalEmulation.hacks & hack_ZeldaMM) == 0
+ ) {
+ renderTarget = gDP.otherMode.depthCompare + 1;
+ }
+ uRenderTarget.set(renderTarget, _force);
+ }
+
+private:
+ iUniform uRenderTarget;
+};
+
+class UScreenCoordsScale : public UniformGroup
+{
+public:
+ UScreenCoordsScale(GLuint _program) {
+ LocateUniform(uScreenCoordsScale);
+ }
+
+ void update(bool _force) override
+ {
+ FrameBuffer * pCurrentBuffer = frameBufferList().getCurrent();
+ const float scaleX = pCurrentBuffer != nullptr ? 1.0f / pCurrentBuffer->m_width : VI.rwidth;
+ const float scaleY = pCurrentBuffer != nullptr ? 1.0f / pCurrentBuffer->m_height : VI.rheight;
+ uScreenCoordsScale.set(2.0f*scaleX, -2.0f*scaleY, _force);
+ }
+
+private:
+ fv2Uniform uScreenCoordsScale;
+};
+
+class UColors : public UniformGroup
+{
+public:
+ UColors(GLuint _program) {
+ LocateUniform(uFogColor);
+ LocateUniform(uCenterColor);
+ LocateUniform(uScaleColor);
+ LocateUniform(uBlendColor);
+ LocateUniform(uEnvColor);
+ LocateUniform(uPrimColor);
+ LocateUniform(uPrimLod);
+ LocateUniform(uK4);
+ LocateUniform(uK5);
+ }
+
+ void update(bool _force) override
+ {
+ uFogColor.set(&gDP.fogColor.r, _force);
+ uCenterColor.set(&gDP.key.center.r, _force);
+ uScaleColor.set(&gDP.key.scale.r, _force);
+ uBlendColor.set(&gDP.blendColor.r, _force);
+ uEnvColor.set(&gDP.envColor.r, _force);
+ uPrimColor.set(&gDP.primColor.r, _force);
+ uPrimLod.set(gDP.primColor.l, _force);
+ uK4.set(gDP.convert.k4*0.0039215689f, _force);
+ uK5.set(gDP.convert.k5*0.0039215689f, _force);
+ }
+
+private:
+ fv4Uniform uFogColor;
+ fv4Uniform uCenterColor;
+ fv4Uniform uScaleColor;
+ fv4Uniform uBlendColor;
+ fv4Uniform uEnvColor;
+ fv4Uniform uPrimColor;
+ fUniform uPrimLod;
+ fUniform uK4;
+ fUniform uK5;
+};
+
+class UTextureSize : public UniformGroup
+{
+public:
+ UTextureSize(GLuint _program, bool _useT0, bool _useT1)
+ : m_useT0(m_useT0)
+ , m_useT1(m_useT1)
+ {
+ LocateUniform(uTextureSize[0]);
+ LocateUniform(uTextureSize[1]);
+ }
+
+ void update(bool _force) override
+ {
+ TextureCache & cache = textureCache();
+ if (m_useT0 && cache.current[0] != NULL)
+ uTextureSize[0].set((float)cache.current[0]->realWidth, (float)cache.current[0]->realHeight, _force);
+ if (m_useT1 && cache.current[1] != NULL)
+ uTextureSize[1].set((float)cache.current[1]->realWidth, (float)cache.current[1]->realHeight, _force);
+ }
+
+private:
+ fv2Uniform uTextureSize[2];
+ bool m_useT0;
+ bool m_useT1;
+};
+
+class UTextureParams : public UniformGroup
+{
+public:
+ UTextureParams(GLuint _program, bool _useT0, bool _useT1)
+ {
+ m_useTile[0] = _useT0;
+ m_useTile[1] = _useT1;
+ LocateUniform(uTexOffset[0]);
+ LocateUniform(uTexOffset[1]);
+ LocateUniform(uCacheShiftScale[0]);
+ LocateUniform(uCacheShiftScale[1]);
+ LocateUniform(uCacheScale[0]);
+ LocateUniform(uCacheScale[1]);
+ LocateUniform(uCacheOffset[0]);
+ LocateUniform(uCacheOffset[1]);
+ LocateUniform(uTexScale);
+ LocateUniform(uCacheFrameBuffer);
+ }
+
+ void update(bool _force) override
+ {
+ int nFB[2] = { 0, 0 };
+ TextureCache & cache = textureCache();
+ for (u32 t = 0; t < 2; ++t) {
+ if (!m_useTile[t])
+ continue;
+
+ if (gSP.textureTile[t] != NULL) {
+ if (gSP.textureTile[t]->textureMode == TEXTUREMODE_BGIMAGE || gSP.textureTile[t]->textureMode == TEXTUREMODE_FRAMEBUFFER_BG)
+ uTexOffset[t].set(0.0f, 0.0f, _force);
+ else {
+ float fuls = gSP.textureTile[t]->fuls;
+ float fult = gSP.textureTile[t]->fult;
+ FrameBuffer * pBuffer = gSP.textureTile[t]->frameBuffer;
+ if (pBuffer != NULL) {
+ if (gSP.textureTile[t]->masks > 0 && gSP.textureTile[t]->clamps == 0)
+ fuls = float(gSP.textureTile[t]->uls % (1 << gSP.textureTile[t]->masks));
+ if (gSP.textureTile[t]->maskt > 0 && gSP.textureTile[t]->clampt == 0)
+ fult = float(gSP.textureTile[t]->ult % (1 << gSP.textureTile[t]->maskt));
+ }
+ uTexOffset[t].set(fuls, fult, _force);
+ }
+ }
+
+ if (cache.current[t] != NULL) {
+ f32 shiftScaleS = 1.0f;
+ f32 shiftScaleT = 1.0f;
+ getTextureShiftScale(t, cache, shiftScaleS, shiftScaleT);
+ uCacheShiftScale[t].set(shiftScaleS, shiftScaleT, _force);
+ uCacheScale[t].set(cache.current[t]->scaleS, cache.current[t]->scaleT, _force);
+ uCacheOffset[t].set(cache.current[t]->offsetS, cache.current[t]->offsetT, _force);
+ nFB[t] = cache.current[t]->frameBufferTexture;
+ }
+ }
+
+ uCacheFrameBuffer.set(nFB[0], nFB[1], _force);
+ uTexScale.set(gSP.texture.scales, gSP.texture.scalet, _force);
+ }
+
+private:
+ bool m_useTile[2];
+ fv2Uniform uTexOffset[2];
+ fv2Uniform uCacheShiftScale[2];
+ fv2Uniform uCacheScale[2];
+ fv2Uniform uCacheOffset[2];
+ fv2Uniform uTexScale;
+ iv2Uniform uCacheFrameBuffer;
+};
+
+
+class ULights : public UniformGroup
+{
+public:
+ ULights(GLuint _program)
+ {
+ char buf[32];
+ for (s32 i = 0; i < 8; ++i) {
+ sprintf(buf, "uLightDirection[%d]", i);
+ uLightDirection[i].loc = glGetUniformLocation(_program, buf);
+ sprintf(buf, "uLightColor[%d]", i);
+ uLightColor[i].loc = glGetUniformLocation(_program, buf);
+ }
+ }
+
+ void update(bool _force) override
+ {
+ for (s32 i = 0; i <= gSP.numLights; ++i) {
+ uLightDirection[i].set(&gSP.lights[i].ix, _force);
+ uLightColor[i].set(&gSP.lights[i].r, _force);
+ }
+ }
+
+private:
+ fv3Uniform uLightDirection[8];
+ fv3Uniform uLightColor[8];
+};
+
+
+/*---------------CombinerProgramUniformFactory-------------*/
+
+void CombinerProgramUniformFactory::buildUniforms(GLuint _program,
+ const CombinerInputs & _inputs,
+ bool _rect,
+ UniformGroups & _uniforms)
+{
+ if (config.generalEmulation.enableNoise != 0)
+ _uniforms.emplace_back(new UNoiseTex(_program));
+
+ if (!m_glInfo.isGLES2)
+ _uniforms.emplace_back(new UDepthTex(_program));
+
+ if (_inputs.usesTexture())
+ _uniforms.emplace_back(new UTextures(_program));
+
+ if (config.video.multisampling != 0)
+ _uniforms.emplace_back(new UMSAATextures(_program));
+
+ if (_inputs.usesTexture())
+ _uniforms.emplace_back(new UFrameBufferInfo(_program));
+
+ _uniforms.emplace_back(new UFog(_program));
+
+ if (config.generalEmulation.enableLegacyBlending == 0) {
+ switch (gDP.otherMode.cycleType) {
+ case G_CYC_1CYCLE:
+ _uniforms.emplace_back(new UBlendMode1Cycle(_program));
+ break;
+ case G_CYC_2CYCLE:
+ _uniforms.emplace_back(new UBlendMode2Cycle(_program));
+ break;
+ }
+ }
+
+ _uniforms.emplace_back(new UDitherMode(_program, _inputs.usesNoise(), m_noiseTexture));
+
+ _uniforms.emplace_back(new UScreenScale(_program));
+
+ if (_inputs.usesLOD()) {
+ _uniforms.emplace_back(new UMipmap1(_program));
+ if (config.generalEmulation.enableLOD != 0)
+ _uniforms.emplace_back(new UMipmap2(_program));
+ }
+
+ _uniforms.emplace_back(new UTexturePersp(_program));
+
+ if (config.texture.bilinearMode == BILINEAR_3POINT)
+ _uniforms.emplace_back(new UTextureFilterMode(_program));
+
+ _uniforms.emplace_back(new UAlphaTestInfo(_program));
+
+ if (!m_glInfo.isGLES2)
+ _uniforms.emplace_back(new UDepthScale(_program));
+
+ if (m_glInfo.imageTextures && config.frameBufferEmulation.N64DepthCompare != 0)
+ _uniforms.emplace_back(new UDepthInfo(_program));
+
+ if (config.generalEmulation.enableFragmentDepthWrite != 0)
+ _uniforms.emplace_back(new URenderTarget(_program));
+
+ _uniforms.emplace_back(new UScreenCoordsScale(_program));
+
+ _uniforms.emplace_back(new UColors(_program));
+
+ if (_inputs.usesTexture()) {
+ _uniforms.emplace_back(new UTextureSize(_program, _inputs.usesTile(0), _inputs.usesTile(1)));
+ if (!_rect)
+ _uniforms.emplace_back(new UTextureParams(_program, _inputs.usesTile(0), _inputs.usesTile(1)));
+ }
+
+ if (_inputs.usesHwLighting())
+ _uniforms.emplace_back(new ULights(_program));
+}
+
+CombinerProgramUniformFactory::CombinerProgramUniformFactory(const opengl::GLInfo & _glInfo,
+ NoiseTexture * _noiseTexture)
+: m_glInfo(_glInfo)
+, m_noiseTexture(_noiseTexture)
+{
+}
+
+CombinerProgramUniformFactory::~CombinerProgramUniformFactory()
+{
+ m_noiseTexture = nullptr;
+}
+
+}
diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.h b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.h
new file mode 100644
index 00000000..668e5776
--- /dev/null
+++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.h
@@ -0,0 +1,22 @@
+#pragma once
+#include
+#include "glsl_CombinerProgramImpl.h"
+
+namespace glsl {
+
+ class NoiseTexture;
+
+ class CombinerProgramUniformFactory
+ {
+ public:
+ CombinerProgramUniformFactory(const opengl::GLInfo & _glInfo, NoiseTexture * _noiseTexture);
+ ~CombinerProgramUniformFactory();
+
+ void buildUniforms(GLuint _program, const CombinerInputs & _inputs, bool _rect, UniformGroups & _uniforms);
+
+ private:
+ const opengl::GLInfo & m_glInfo;
+ NoiseTexture * m_noiseTexture;
+ };
+
+}
diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_NoiseTexture.cpp b/src/Graphics/OpenGLContext/GLSL/glsl_NoiseTexture.cpp
new file mode 100644
index 00000000..32e82da2
--- /dev/null
+++ b/src/Graphics/OpenGLContext/GLSL/glsl_NoiseTexture.cpp
@@ -0,0 +1,116 @@
+#include "glsl_NoiseTexture.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace glsl {
+
+ struct PBOBinder {
+ PBOBinder(GLenum _target, GLuint _PBO) : m_target(_target)
+ {
+ glBindBuffer(m_target, _PBO);
+ }
+ ~PBOBinder() {
+ glBindBuffer(m_target, 0);
+ }
+ GLenum m_target;
+ };
+
+
+ NoiseTexture::NoiseTexture()
+ : m_pTexture(nullptr)
+ , m_PBO(0)
+ , m_DList(0)
+ {
+ init();
+ }
+
+ NoiseTexture::~NoiseTexture()
+ {
+ destroy();
+ }
+
+ void NoiseTexture::init()
+ {
+ if (config.generalEmulation.enableNoise == 0)
+ return;
+ m_pTexture = textureCache().addFrameBufferTexture(false);
+ m_pTexture->format = G_IM_FMT_RGBA;
+ m_pTexture->clampS = 1;
+ m_pTexture->clampT = 1;
+ m_pTexture->frameBufferTexture = CachedTexture::fbOneSample;
+ m_pTexture->maskS = 0;
+ m_pTexture->maskT = 0;
+ m_pTexture->mirrorS = 0;
+ m_pTexture->mirrorT = 0;
+ m_pTexture->realWidth = 640;
+ m_pTexture->realHeight = 580;
+ m_pTexture->textureBytes = m_pTexture->realWidth * m_pTexture->realHeight;
+ textureCache().addFrameBufferTextureSize(m_pTexture->textureBytes);
+
+ {
+ graphics::Context::InitTextureParams params;
+ params.handle = graphics::ObjectHandle(m_pTexture->glName);
+ params.width = m_pTexture->realWidth;
+ params.height = m_pTexture->realHeight;
+ params.internalFormat = graphics::internalcolor::RED;
+ params.format = graphics::color::RED;
+ params.dataType = graphics::datatype::UNSIGNED_BYTE;
+ gfxContext.init2DTexture(params);
+ }
+ {
+ graphics::Context::TexParameters params;
+ params.handle = graphics::ObjectHandle(m_pTexture->glName);
+ params.target = graphics::target::TEXTURE_2D;
+ params.textureUnitIndex = 0;
+ params.minFilter = graphics::textureParameters::FILTER_NEAREST;
+ params.magFilter = graphics::textureParameters::FILTER_NEAREST;
+ gfxContext.setTextureParameters(params);
+ }
+
+ // TODO rewrite in GL independent way
+ // Generate Pixel Buffer Object. Initialize it with max buffer size.
+ glGenBuffers(1, &m_PBO);
+ PBOBinder binder(GL_PIXEL_UNPACK_BUFFER, m_PBO);
+ glBufferData(GL_PIXEL_UNPACK_BUFFER, 640 * 580, nullptr, GL_DYNAMIC_DRAW);
+ }
+
+ void NoiseTexture::destroy()
+ {
+ if (m_pTexture != nullptr) {
+ textureCache().removeFrameBufferTexture(m_pTexture);
+ m_pTexture = nullptr;
+ }
+ glDeleteBuffers(1, &m_PBO);
+ m_PBO = 0;
+ }
+
+ void NoiseTexture::update()
+ {
+ if (m_PBO == 0 || m_pTexture == nullptr)
+ return;
+ if (m_DList == video().getBuffersSwapCount() || config.generalEmulation.enableNoise == 0)
+ return;
+ const u32 dataSize = VI.width*VI.height;
+ if (dataSize == 0)
+ return;
+ PBOBinder binder(GL_PIXEL_UNPACK_BUFFER, m_PBO);
+ GLubyte* ptr = (GLubyte*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, dataSize, GL_MAP_WRITE_BIT);
+ if (ptr == nullptr)
+ return;
+ for (u32 y = 0; y < VI.height; ++y) {
+ for (u32 x = 0; x < VI.width; ++x)
+ ptr[x + y*VI.width] = rand() & 0xFF;
+ }
+ glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); // release the mapped buffer
+
+ glActiveTexture(GL_TEXTURE0 + g_noiseTexIndex);
+ glBindTexture(GL_TEXTURE_2D, m_pTexture->glName);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VI.width, VI.height, GL_RED, GL_UNSIGNED_BYTE, 0);
+ m_DList = video().getBuffersSwapCount();
+ }
+
+}
diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_NoiseTexture.h b/src/Graphics/OpenGLContext/GLSL/glsl_NoiseTexture.h
new file mode 100644
index 00000000..1df3ce0b
--- /dev/null
+++ b/src/Graphics/OpenGLContext/GLSL/glsl_NoiseTexture.h
@@ -0,0 +1,24 @@
+#pragma once
+#include
+#include
+
+struct CachedTexture;
+
+namespace glsl {
+
+ class NoiseTexture
+ {
+ public:
+ NoiseTexture();
+ ~NoiseTexture();
+
+ void init();
+ void destroy();
+ void update();
+
+ private:
+ CachedTexture * m_pTexture;
+ GLuint m_PBO;
+ u32 m_DList;
+ };
+}
diff --git a/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp b/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp
index eb95b6b6..5c9140df 100644
--- a/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp
+++ b/src/Graphics/OpenGLContext/opengl_ContextImpl.cpp
@@ -1,6 +1,7 @@
#include
#include
#include "opengl_ContextImpl.h"
+#include "GLSL/glsl_CombinerProgramBuilder.h"
using namespace opengl;
@@ -35,6 +36,8 @@ void ContextImpl::init()
m_initRenderbuffer.reset(bufferObjectFactory.getInitRenderbuffer());
m_addFramebufferRenderTarget.reset(bufferObjectFactory.getAddFramebufferRenderTarget());
}
+
+ m_combinerProgramBuilder.reset(new glsl::CombinerProgramBuilder(m_glInfo));
}
void ContextImpl::destroy()
@@ -48,6 +51,9 @@ void ContextImpl::destroy()
m_createRenderbuffer.reset(nullptr);
m_initRenderbuffer.reset(nullptr);
m_addFramebufferRenderTarget.reset(nullptr);
+
+
+ m_combinerProgramBuilder.reset(nullptr);
}
graphics::ObjectHandle ContextImpl::createTexture(graphics::Parameter _target)
@@ -103,5 +109,5 @@ void ContextImpl::addFrameBufferRenderTarget(const graphics::Context::FrameBuffe
graphics::CombinerProgram * ContextImpl::createCombinerProgram(Combiner & _color, Combiner & _alpha, const CombinerKey & _key)
{
- return nullptr;
+ return m_combinerProgramBuilder->buildCombinerProgram(_color, _alpha, _key);
}
diff --git a/src/Graphics/OpenGLContext/opengl_ContextImpl.h b/src/Graphics/OpenGLContext/opengl_ContextImpl.h
index 48e2693e..7c7bf1c6 100644
--- a/src/Graphics/OpenGLContext/opengl_ContextImpl.h
+++ b/src/Graphics/OpenGLContext/opengl_ContextImpl.h
@@ -6,6 +6,10 @@
#include "opengl_GLInfo.h"
#include "opengl_CachedFunctions.h"
+namespace glsl {
+ class CombinerProgramBuilder;
+}
+
namespace opengl {
class ContextImpl : public graphics::ContextImpl
@@ -49,6 +53,7 @@ namespace opengl {
std::unique_ptr m_initRenderbuffer;
std::unique_ptr m_addFramebufferRenderTarget;
+ std::unique_ptr m_combinerProgramBuilder;
GLInfo m_glInfo;
};