Added new swizzle parameters to Sampler's state

The new parameters are: swizzleR, swizzleG, swizzleB, swizzleA.

Also, parameters sent from the context that can be either
originating from the Texture object or the Sampler object
are now sent from the correct origin.

An implementation for the swizzleR, swizzleG, swizzleB, swizzleA
parameters was done in SamplerCore. All related dEQP tests pass.

Change-Id: I45405a0d241d0e70a91a3c56357c7bc04c7dc75a
Reviewed-on: https://swiftshader-review.googlesource.com/4017
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 85f2386..db33e8d 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -3061,16 +3061,39 @@
 

 			if(texture->isSamplerComplete())

             {

-                GLenum wrapS = texture->getWrapS();

-                GLenum wrapT = texture->getWrapT();

-				GLenum wrapR = texture->getWrapR();

-                GLenum texFilter = texture->getMinFilter();

-                GLenum magFilter = texture->getMagFilter();

+				GLenum wrapS, wrapT, wrapR, texFilter, magFilter;

+

+				Sampler *samplerObject = mState.sampler[textureUnit];

+				if(samplerObject)

+				{

+					wrapS = samplerObject->getWrapS();

+					wrapT = samplerObject->getWrapT();

+					wrapR = samplerObject->getWrapR();

+					texFilter = samplerObject->getMinFilter();

+					magFilter = samplerObject->getMagFilter();

+				}

+				else

+				{

+					wrapS = texture->getWrapS();

+					wrapT = texture->getWrapT();

+					wrapR = texture->getWrapR();

+					texFilter = texture->getMinFilter();

+					magFilter = texture->getMagFilter();

+				}

 				GLfloat maxAnisotropy = texture->getMaxAnisotropy();

 

+				GLenum swizzleR = texture->getSwizzleR();

+				GLenum swizzleG = texture->getSwizzleG();

+				GLenum swizzleB = texture->getSwizzleB();

+				GLenum swizzleA = texture->getSwizzleA();

+

 				device->setAddressingModeU(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapS));

 				device->setAddressingModeV(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapT));

 				device->setAddressingModeW(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapR));

+				device->setSwizzleR(samplerType, samplerIndex, es2sw::ConvertSwizzleType(swizzleR));

+				device->setSwizzleG(samplerType, samplerIndex, es2sw::ConvertSwizzleType(swizzleG));

+				device->setSwizzleB(samplerType, samplerIndex, es2sw::ConvertSwizzleType(swizzleB));

+				device->setSwizzleA(samplerType, samplerIndex, es2sw::ConvertSwizzleType(swizzleA));

 

 				sw::FilterType minFilter;

 				sw::MipmapType mipFilter;

diff --git a/src/OpenGL/libGLESv2/utilities.cpp b/src/OpenGL/libGLESv2/utilities.cpp
index 0b28b78..6442993 100644
--- a/src/OpenGL/libGLESv2/utilities.cpp
+++ b/src/OpenGL/libGLESv2/utilities.cpp
@@ -822,6 +822,22 @@
 		return sw::ADDRESSING_WRAP;

 	}

 

+	sw::SwizzleType ConvertSwizzleType(GLenum swizzleType)

+	{

+		switch(swizzleType)

+		{

+		case GL_RED:   return sw::SWIZZLE_RED;

+		case GL_GREEN: return sw::SWIZZLE_GREEN;

+		case GL_BLUE:  return sw::SWIZZLE_BLUE;

+		case GL_ALPHA: return sw::SWIZZLE_ALPHA;

+		case GL_ZERO:  return sw::SWIZZLE_ZERO;

+		case GL_ONE:   return sw::SWIZZLE_ONE;

+		default: UNREACHABLE(swizzleType);

+		}

+

+		return sw::SWIZZLE_RED;

+	};

+

 	sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace)

 	{

 		switch(cullFace)

diff --git a/src/OpenGL/libGLESv2/utilities.h b/src/OpenGL/libGLESv2/utilities.h
index 27ff9df..cc1a1d1 100644
--- a/src/OpenGL/libGLESv2/utilities.h
+++ b/src/OpenGL/libGLESv2/utilities.h
@@ -68,6 +68,7 @@
 	sw::LogicalOperation ConvertLogicalOperation(GLenum logicalOperation);

 	sw::StencilOperation ConvertStencilOp(GLenum stencilOp);

 	sw::AddressingMode ConvertTextureWrap(GLenum wrap);

+	sw::SwizzleType ConvertSwizzleType(GLenum swizzleType);

 	sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace);

 	unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha);

 	sw::FilterType ConvertMagFilter(GLenum magFilter);

diff --git a/src/Renderer/PixelProcessor.cpp b/src/Renderer/PixelProcessor.cpp
index 858772a..0803291 100644
--- a/src/Renderer/PixelProcessor.cpp
+++ b/src/Renderer/PixelProcessor.cpp
@@ -416,6 +416,42 @@
 		else ASSERT(false);
 	}
 
+	void PixelProcessor::setSwizzleR(unsigned int sampler, SwizzleType swizzleR)
+	{
+		if(sampler < TEXTURE_IMAGE_UNITS)
+		{
+			context->sampler[sampler].setSwizzleR(swizzleR);
+		}
+		else ASSERT(false);
+	}
+
+	void PixelProcessor::setSwizzleG(unsigned int sampler, SwizzleType swizzleG)
+	{
+		if(sampler < TEXTURE_IMAGE_UNITS)
+		{
+			context->sampler[sampler].setSwizzleG(swizzleG);
+		}
+		else ASSERT(false);
+	}
+
+	void PixelProcessor::setSwizzleB(unsigned int sampler, SwizzleType swizzleB)
+	{
+		if(sampler < TEXTURE_IMAGE_UNITS)
+		{
+			context->sampler[sampler].setSwizzleB(swizzleB);
+		}
+		else ASSERT(false);
+	}
+
+	void PixelProcessor::setSwizzleA(unsigned int sampler, SwizzleType swizzleA)
+	{
+		if(sampler < TEXTURE_IMAGE_UNITS)
+		{
+			context->sampler[sampler].setSwizzleA(swizzleA);
+		}
+		else ASSERT(false);
+	}
+
 	void PixelProcessor::setWriteSRGB(bool sRGB)
 	{
 		context->setWriteSRGB(sRGB);
diff --git a/src/Renderer/PixelProcessor.hpp b/src/Renderer/PixelProcessor.hpp
index 310d809..003c43c 100644
--- a/src/Renderer/PixelProcessor.hpp
+++ b/src/Renderer/PixelProcessor.hpp
@@ -225,6 +225,10 @@
 		virtual void setMipmapLOD(unsigned int sampler, float bias);

 		virtual void setBorderColor(unsigned int sampler, const Color<float> &borderColor);

 		virtual void setMaxAnisotropy(unsigned int sampler, float maxAnisotropy);

+		virtual void setSwizzleR(unsigned int sampler, SwizzleType swizzleR);

+		virtual void setSwizzleG(unsigned int sampler, SwizzleType swizzleG);

+		virtual void setSwizzleB(unsigned int sampler, SwizzleType swizzleB);

+		virtual void setSwizzleA(unsigned int sampler, SwizzleType swizzleA);

 

 		virtual void setWriteSRGB(bool sRGB);

 		virtual void setDepthBufferEnable(bool depthBufferEnable);

diff --git a/src/Renderer/Renderer.cpp b/src/Renderer/Renderer.cpp
index e17bc11..6e86551 100644
--- a/src/Renderer/Renderer.cpp
+++ b/src/Renderer/Renderer.cpp
@@ -2231,6 +2231,54 @@
 		}
 	}
 
+	void Renderer::setSwizzleR(SamplerType type, int sampler, SwizzleType swizzleR)
+	{
+		if(type == SAMPLER_PIXEL)
+		{
+			PixelProcessor::setSwizzleR(sampler, swizzleR);
+		}
+		else
+		{
+			VertexProcessor::setSwizzleR(sampler, swizzleR);
+		}
+	}
+
+	void Renderer::setSwizzleG(SamplerType type, int sampler, SwizzleType swizzleG)
+	{
+		if(type == SAMPLER_PIXEL)
+		{
+			PixelProcessor::setSwizzleG(sampler, swizzleG);
+		}
+		else
+		{
+			VertexProcessor::setSwizzleG(sampler, swizzleG);
+		}
+	}
+
+	void Renderer::setSwizzleB(SamplerType type, int sampler, SwizzleType swizzleB)
+	{
+		if(type == SAMPLER_PIXEL)
+		{
+			PixelProcessor::setSwizzleB(sampler, swizzleB);
+		}
+		else
+		{
+			VertexProcessor::setSwizzleB(sampler, swizzleB);
+		}
+	}
+
+	void Renderer::setSwizzleA(SamplerType type, int sampler, SwizzleType swizzleA)
+	{
+		if(type == SAMPLER_PIXEL)
+		{
+			PixelProcessor::setSwizzleA(sampler, swizzleA);
+		}
+		else
+		{
+			VertexProcessor::setSwizzleA(sampler, swizzleA);
+		}
+	}
+
 	void Renderer::setPointSpriteEnable(bool pointSpriteEnable)
 	{
 		context->setPointSpriteEnable(pointSpriteEnable);
diff --git a/src/Renderer/Renderer.hpp b/src/Renderer/Renderer.hpp
index 235fc1c..3b85cdb 100644
--- a/src/Renderer/Renderer.hpp
+++ b/src/Renderer/Renderer.hpp
@@ -325,6 +325,10 @@
 		virtual void setMipmapLOD(SamplerType type, int sampler, float bias);
 		virtual void setBorderColor(SamplerType type, int sampler, const Color<float> &borderColor);
 		virtual void setMaxAnisotropy(SamplerType type, int sampler, float maxAnisotropy);
+		virtual void setSwizzleR(SamplerType type, int sampler, SwizzleType swizzleR);
+		virtual void setSwizzleG(SamplerType type, int sampler, SwizzleType swizzleG);
+		virtual void setSwizzleB(SamplerType type, int sampler, SwizzleType swizzleB);
+		virtual void setSwizzleA(SamplerType type, int sampler, SwizzleType swizzleA);
 		
 		virtual void setPointSpriteEnable(bool pointSpriteEnable);
 		virtual void setPointScaleEnable(bool pointScaleEnable);
diff --git a/src/Renderer/Sampler.cpp b/src/Renderer/Sampler.cpp
index f4d5061..93b7134 100644
--- a/src/Renderer/Sampler.cpp
+++ b/src/Renderer/Sampler.cpp
@@ -87,6 +87,10 @@
 			state.mipmapFilter = mipmapFilter();
 			state.hasNPOTTexture = hasNPOTTexture();
 			state.sRGB = sRGB && Surface::isSRGBreadable(externalTextureFormat);
+			state.swizzleR = swizzleR;
+			state.swizzleG = swizzleG;
+			state.swizzleB = swizzleB;
+			state.swizzleA = swizzleA;
 
 			#if PERF_PROFILE
 				state.compressedFormat = Surface::isCompressed(externalTextureFormat);
@@ -303,6 +307,26 @@
 		texture.maxAnisotropy = maxAnisotropy;
 	}
 
+	void Sampler::setSwizzleR(SwizzleType swizzleR)
+	{
+		this->swizzleR = swizzleR;
+	}
+	
+	void Sampler::setSwizzleG(SwizzleType swizzleG)
+	{
+		this->swizzleG = swizzleG;
+	}
+
+	void Sampler::setSwizzleB(SwizzleType swizzleB)
+	{
+		this->swizzleB = swizzleB;
+	}
+
+	void Sampler::setSwizzleA(SwizzleType swizzleA)
+	{
+		this->swizzleA = swizzleA;
+	}
+
 	void Sampler::setFilterQuality(FilterType maximumFilterQuality)
 	{
 		Sampler::maximumTextureFilterQuality = maximumFilterQuality;
diff --git a/src/Renderer/Sampler.hpp b/src/Renderer/Sampler.hpp
index ae8602b..a41bb29 100644
--- a/src/Renderer/Sampler.hpp
+++ b/src/Renderer/Sampler.hpp
@@ -113,6 +113,18 @@
 		ADDRESSING_LAST = ADDRESSING_BORDER
 	};
 
+	enum SwizzleType : unsigned int
+	{
+		SWIZZLE_RED,
+		SWIZZLE_GREEN,
+		SWIZZLE_BLUE,
+		SWIZZLE_ALPHA,
+		SWIZZLE_ZERO,
+		SWIZZLE_ONE,
+
+		SWIZZLE_LAST = SWIZZLE_ONE
+	};
+
 	class Sampler
 	{
 	public:
@@ -129,6 +141,10 @@
 			MipmapType mipmapFilter        : BITS(FILTER_LAST);
 			bool hasNPOTTexture	           : 1;
 			bool sRGB                      : 1;
+			SwizzleType swizzleR           : BITS(SWIZZLE_LAST);
+			SwizzleType swizzleG           : BITS(SWIZZLE_LAST);
+			SwizzleType swizzleB           : BITS(SWIZZLE_LAST);
+			SwizzleType swizzleA           : BITS(SWIZZLE_LAST);
 
 			#if PERF_PROFILE
 			bool compressedFormat          : 1;
@@ -152,6 +168,10 @@
 		void setReadSRGB(bool sRGB);
 		void setBorderColor(const Color<float> &borderColor);
 		void setMaxAnisotropy(float maxAnisotropy);
+		void setSwizzleR(SwizzleType swizzleR);
+		void setSwizzleG(SwizzleType swizzleG);
+		void setSwizzleB(SwizzleType swizzleB);
+		void setSwizzleA(SwizzleType swizzleA);
 
 		static void setFilterQuality(FilterType maximumFilterQuality);
 		static void setMipmapQuality(MipmapType maximumFilterQuality);
@@ -185,6 +205,10 @@
 		bool sRGB;
 		bool gather;
 
+		SwizzleType swizzleR;
+		SwizzleType swizzleG;
+		SwizzleType swizzleB;
+		SwizzleType swizzleA;
 		Texture texture;
 		float exp2LOD;
 
diff --git a/src/Renderer/VertexProcessor.cpp b/src/Renderer/VertexProcessor.cpp
index ae0be80..d4b9a99 100644
--- a/src/Renderer/VertexProcessor.cpp
+++ b/src/Renderer/VertexProcessor.cpp
@@ -545,6 +545,42 @@
 		else ASSERT(false);
 	}
 
+	void VertexProcessor::setSwizzleR(unsigned int sampler, SwizzleType swizzleR)
+	{
+		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
+		{
+			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setSwizzleR(swizzleR);
+		}
+		else ASSERT(false);
+	}
+
+	void VertexProcessor::setSwizzleG(unsigned int sampler, SwizzleType swizzleG)
+	{
+		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
+		{
+			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setSwizzleG(swizzleG);
+		}
+		else ASSERT(false);
+	}
+
+	void VertexProcessor::setSwizzleB(unsigned int sampler, SwizzleType swizzleB)
+	{
+		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
+		{
+			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setSwizzleB(swizzleB);
+		}
+		else ASSERT(false);
+	}
+
+	void VertexProcessor::setSwizzleA(unsigned int sampler, SwizzleType swizzleA)
+	{
+		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
+		{
+			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setSwizzleA(swizzleA);
+		}
+		else ASSERT(false);
+	}
+
 	void VertexProcessor::setPointSize(float pointSize)
 	{
 		point.pointSize = replicate(pointSize);
diff --git a/src/Renderer/VertexProcessor.hpp b/src/Renderer/VertexProcessor.hpp
index 5d17a91..a8ba461 100644
--- a/src/Renderer/VertexProcessor.hpp
+++ b/src/Renderer/VertexProcessor.hpp
@@ -243,6 +243,10 @@
 		virtual void setMipmapLOD(unsigned int sampler, float bias);

 		virtual void setBorderColor(unsigned int sampler, const Color<float> &borderColor);

 		virtual void setMaxAnisotropy(unsigned int stage, float maxAnisotropy);

+		virtual void setSwizzleR(unsigned int sampler, SwizzleType swizzleR);

+		virtual void setSwizzleG(unsigned int sampler, SwizzleType swizzleG);

+		virtual void setSwizzleB(unsigned int sampler, SwizzleType swizzleB);

+		virtual void setSwizzleA(unsigned int sampler, SwizzleType swizzleA);

 

 		virtual void setPointSize(float pointSize);

 		virtual void setPointSizeMin(float pointSizeMin);

diff --git a/src/Shader/SamplerCore.cpp b/src/Shader/SamplerCore.cpp
index b13eb1b..c760ff7 100644
--- a/src/Shader/SamplerCore.cpp
+++ b/src/Shader/SamplerCore.cpp
@@ -14,6 +14,37 @@
 #include "Constants.hpp"
 #include "Debug.hpp"
 
+namespace
+{
+	void applySwizzle(sw::SwizzleType swizzle, sw::Short4& s, const sw::Vector4s& c)
+	{
+		switch(swizzle)
+		{
+		case sw::SWIZZLE_RED:	s = c.x; break;
+		case sw::SWIZZLE_GREEN: s = c.y; break;
+		case sw::SWIZZLE_BLUE:  s = c.z; break;
+		case sw::SWIZZLE_ALPHA: s = c.w; break;
+		case sw::SWIZZLE_ZERO:  s = sw::Short4(0x0000, 0x0000, 0x0000, 0x0000); break;
+		case sw::SWIZZLE_ONE:   s = sw::Short4(0x1000, 0x1000, 0x1000, 0x1000); break;
+		default: ASSERT(false);
+		}
+	}
+
+	void applySwizzle(sw::SwizzleType swizzle, sw::Float4& f, const sw::Vector4f& c)
+	{
+		switch(swizzle)
+		{
+		case sw::SWIZZLE_RED:	f = c.x; break;
+		case sw::SWIZZLE_GREEN: f = c.y; break;
+		case sw::SWIZZLE_BLUE:  f = c.z; break;
+		case sw::SWIZZLE_ALPHA: f = c.w; break;
+		case sw::SWIZZLE_ZERO:  f = sw::Float4(0.0f, 0.0f, 0.0f, 0.0f); break;
+		case sw::SWIZZLE_ONE:   f = sw::Float4(1.0f, 1.0f, 1.0f, 1.0f); break;
+		default: ASSERT(false);
+		}
+	}
+}
+
 namespace sw
 {
 	SamplerCore::SamplerCore(Pointer<Byte> &constants, const Sampler::State &state) : constants(constants), state(state)
@@ -215,6 +246,19 @@
 				}
 			}
 		}
+
+		if(fixed12 &&
+		   ((state.swizzleR != SWIZZLE_RED) ||
+		    (state.swizzleG != SWIZZLE_GREEN) ||
+		    (state.swizzleB != SWIZZLE_BLUE) ||
+		    (state.swizzleA != SWIZZLE_ALPHA)))
+		{
+			const Vector4s col(c);
+			applySwizzle(state.swizzleR, c.x, col);
+			applySwizzle(state.swizzleG, c.y, col);
+			applySwizzle(state.swizzleB, c.z, col);
+			applySwizzle(state.swizzleA, c.w, col);
+		}
 	}
 
 	void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, bool bias, bool gradients, bool lodProvided)
@@ -401,6 +445,18 @@
 				}
 			}
 		}
+
+		if((state.swizzleR != SWIZZLE_RED) ||
+		   (state.swizzleG != SWIZZLE_GREEN) ||
+		   (state.swizzleB != SWIZZLE_BLUE) ||
+		   (state.swizzleA != SWIZZLE_ALPHA))
+		{
+			const Vector4f col(c);
+			applySwizzle(state.swizzleR, c.x, col);
+			applySwizzle(state.swizzleG, c.y, col);
+			applySwizzle(state.swizzleB, c.z, col);
+			applySwizzle(state.swizzleA, c.w, col);
+		}
 	}
 
 	void SamplerCore::border(Short4 &mask, Float4 &coordinates)