Add SwiftShader source to repo

Oct 6 code drop from Transgaming
Review URL: https://chromereviews.googleplex.com/3846015
diff --git a/src/Renderer/Sampler.cpp b/src/Renderer/Sampler.cpp
new file mode 100644
index 0000000..1b7c651
--- /dev/null
+++ b/src/Renderer/Sampler.cpp
@@ -0,0 +1,400 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2011 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+#include "Sampler.hpp"
+
+#include "MetaMacro.hpp"
+#include "Context.hpp"
+#include "Surface.hpp"
+#include "CPUID.hpp"
+#include "PixelRoutine.hpp"
+#include "Debug.hpp"
+
+#include <memory.h>
+#include <string.h>
+
+namespace sw
+{
+	FilterType Sampler::maximumTextureFilterQuality = FILTER_LINEAR;
+	MipmapType Sampler::maximumMipmapFilterQuality = MIPMAP_POINT;
+
+	Sampler::State::State()
+	{
+		memset(this, 0, sizeof(State));
+	}
+
+	Sampler::Sampler()
+	{
+		// FIXME: Mipmap::init
+		static unsigned int zero = 0x00FF00FF;
+
+		for(int level = 0; level < MIPMAP_LEVELS; level++)
+		{
+			Mipmap &mipmap = texture.mipmap[level];
+
+			memset(&mipmap, 0, sizeof(Mipmap));
+
+			for(int face = 0; face < 6; face++)   
+			{
+				mipmap.buffer[face] = &zero;
+			}
+
+			mipmap.uFrac = 16;
+			mipmap.vFrac = 16;
+			mipmap.wFrac = 16;
+		}
+
+		externalTextureFormat = FORMAT_NULL;
+		internalTextureFormat = FORMAT_NULL;
+		textureType = TEXTURE_NULL;
+
+		textureFilter = FILTER_LINEAR;
+		addressingModeU = ADDRESSING_WRAP;
+		addressingModeV = ADDRESSING_WRAP;
+		addressingModeW = ADDRESSING_WRAP;
+		mipmapFilterState = MIPMAP_NONE;
+		sRGB = false;
+		gather = false;
+
+		texture.LOD = 0.0f;
+		exp2LOD = 1.0f;
+	}
+
+	Sampler::~Sampler()
+	{
+	}
+
+	Sampler::State Sampler::samplerState() const
+	{
+		State state;
+
+		if(textureType != TEXTURE_NULL)
+		{
+			state.textureType = textureType;
+			state.textureFormat = internalTextureFormat;
+			state.textureFilter = getTextureFilter();
+			state.addressingModeU = getAddressingModeU();
+			state.addressingModeV = getAddressingModeV();
+			state.addressingModeW = getAddressingModeW();
+			state.mipmapFilter = mipmapFilter();
+			state.hasNPOTTexture = hasNPOTTexture();
+			state.sRGB = sRGB && Surface::isSRGBreadable(externalTextureFormat);
+
+			#if PERF_PROFILE
+				state.compressedFormat = Surface::isCompressed(externalTextureFormat);
+			#endif
+		}
+
+		return state;
+	}
+
+	void Sampler::setTextureLevel(int face, int level, Surface *surface, TextureType type)
+	{
+		if(surface)
+		{
+			Mipmap &mipmap = texture.mipmap[level];
+
+			mipmap.buffer[face] = surface->lockInternal(0, 0, 0, LOCK_UNLOCKED, PRIVATE);
+
+			if(face == 0)
+			{
+				externalTextureFormat = surface->getExternalFormat();
+				internalTextureFormat = surface->getInternalFormat();
+
+				int width = surface->getInternalWidth();
+				int height = surface->getInternalHeight();
+				int depth = surface->getInternalDepth();
+				int pitchP = surface->getInternalPitchP();
+				int sliceP = surface->getInternalSliceP();
+
+				int logWidth = log2(width);
+				int logHeight = log2(height);
+				int logDepth = log2(depth);
+
+				if(level == 0)
+				{
+					texture.widthHeightLOD[0] = width * exp2LOD;
+					texture.widthHeightLOD[1] = width * exp2LOD;
+					texture.widthHeightLOD[2] = height * exp2LOD;
+					texture.widthHeightLOD[3] = height * exp2LOD;
+
+					texture.widthLOD[0] = width * exp2LOD;
+					texture.widthLOD[1] = width * exp2LOD;
+					texture.widthLOD[2] = width * exp2LOD;
+					texture.widthLOD[3] = width * exp2LOD;
+
+					texture.heightLOD[0] = height * exp2LOD;
+					texture.heightLOD[1] = height * exp2LOD;
+					texture.heightLOD[2] = height * exp2LOD;
+					texture.heightLOD[3] = height * exp2LOD;
+
+					texture.depthLOD[0] = depth * exp2LOD;
+					texture.depthLOD[1] = depth * exp2LOD;
+					texture.depthLOD[2] = depth * exp2LOD;
+					texture.depthLOD[3] = depth * exp2LOD;
+				}
+
+				if(!Surface::isFloatFormat(internalTextureFormat))
+				{
+					mipmap.uInt = logWidth;
+					mipmap.vInt = logHeight;
+					mipmap.wInt = logDepth;
+					mipmap.uFrac = 16 - logWidth;
+					mipmap.vFrac = 16 - logHeight;
+					mipmap.wFrac = 16 - logDepth;
+				}
+				else
+				{
+					mipmap.fWidth[0] = (float)width / 65536.0f;
+					mipmap.fWidth[1] = (float)width / 65536.0f;
+					mipmap.fWidth[2] = (float)width / 65536.0f;
+					mipmap.fWidth[3] = (float)width / 65536.0f;
+
+					mipmap.fHeight[0] = (float)height / 65536.0f;
+					mipmap.fHeight[1] = (float)height / 65536.0f;
+					mipmap.fHeight[2] = (float)height / 65536.0f;
+					mipmap.fHeight[3] = (float)height / 65536.0f;
+
+					mipmap.fDepth[0] = (float)depth / 65536.0f;
+					mipmap.fDepth[1] = (float)depth / 65536.0f;
+					mipmap.fDepth[2] = (float)depth / 65536.0f;
+					mipmap.fDepth[3] = (float)depth / 65536.0f;
+				}
+
+				short halfTexelU = isPow2(width)  ? 0x8000 >> logWidth  : 0x8000 / width;
+				short halfTexelV = isPow2(height) ? 0x8000 >> logHeight : 0x8000 / height;
+				short halfTexelW = isPow2(depth)  ? 0x8000 >> logDepth  : 0x8000 / depth;
+
+				mipmap.uHalf[0] = halfTexelU;
+				mipmap.uHalf[1] = halfTexelU;
+				mipmap.uHalf[2] = halfTexelU;
+				mipmap.uHalf[3] = halfTexelU;
+
+				mipmap.vHalf[0] = halfTexelV;
+				mipmap.vHalf[1] = halfTexelV;
+				mipmap.vHalf[2] = halfTexelV;
+				mipmap.vHalf[3] = halfTexelV;
+
+				mipmap.wHalf[0] = halfTexelW;
+				mipmap.wHalf[1] = halfTexelW;
+				mipmap.wHalf[2] = halfTexelW;
+				mipmap.wHalf[3] = halfTexelW;
+
+				mipmap.width[0] = width;
+				mipmap.width[1] = width;
+				mipmap.width[2] = width;
+				mipmap.width[3] = width;
+
+				mipmap.height[0] = height;
+				mipmap.height[1] = height;
+				mipmap.height[2] = height;
+				mipmap.height[3] = height;
+
+				mipmap.depth[0] = depth;
+				mipmap.depth[1] = depth;
+				mipmap.depth[2] = depth;
+				mipmap.depth[3] = depth;
+
+				mipmap.onePitchP[0] = 1;
+				mipmap.onePitchP[1] = pitchP;
+				mipmap.onePitchP[2] = 1;
+				mipmap.onePitchP[3] = pitchP;
+
+				mipmap.sliceP[0] = sliceP;
+				mipmap.sliceP[1] = sliceP;
+			}
+		}
+
+		textureType = type;
+	}
+
+	void Sampler::setTextureFilter(FilterType textureFilter)
+	{
+		this->textureFilter = (FilterType)min(textureFilter, maximumTextureFilterQuality);
+	}
+
+	void Sampler::setMipmapFilter(MipmapType mipmapFilter)
+	{
+		mipmapFilterState = (MipmapType)min(mipmapFilter, maximumMipmapFilterQuality);
+	}
+
+	void Sampler::setGatherEnable(bool enable)
+	{
+		gather = enable;
+	}
+
+	void Sampler::setAddressingModeU(AddressingMode addressingMode)
+	{
+		addressingModeU = addressingMode;
+	}
+
+	void Sampler::setAddressingModeV(AddressingMode addressingMode)
+	{
+		addressingModeV = addressingMode;
+	}
+
+	void Sampler::setAddressingModeW(AddressingMode addressingMode)
+	{
+		addressingModeW = addressingMode;
+	}
+
+	void Sampler::setReadSRGB(bool sRGB)
+	{
+		this->sRGB = sRGB;
+	}
+
+	void Sampler::setBorderColor(const Color<float> &borderColor)
+	{
+		// FIXME: Compact into generic function   // FIXME: Clamp
+		short r = iround(0xFFFF * borderColor.r);
+		short g = iround(0xFFFF * borderColor.g);
+		short b = iround(0xFFFF * borderColor.b);
+		short a = iround(0xFFFF * borderColor.a);
+
+		texture.borderColor4[0][0] = texture.borderColor4[0][1] = texture.borderColor4[0][2] = texture.borderColor4[0][3] = r;
+		texture.borderColor4[1][0] = texture.borderColor4[1][1] = texture.borderColor4[1][2] = texture.borderColor4[1][3] = g;
+		texture.borderColor4[2][0] = texture.borderColor4[2][1] = texture.borderColor4[2][2] = texture.borderColor4[2][3] = b;
+		texture.borderColor4[3][0] = texture.borderColor4[3][1] = texture.borderColor4[3][2] = texture.borderColor4[3][3] = a;
+
+		texture.borderColorF[0][0] = texture.borderColorF[0][1] = texture.borderColorF[0][2] = texture.borderColorF[0][3] = borderColor.r;
+		texture.borderColorF[1][0] = texture.borderColorF[1][1] = texture.borderColorF[1][2] = texture.borderColorF[1][3] = borderColor.g;
+		texture.borderColorF[2][0] = texture.borderColorF[2][1] = texture.borderColorF[2][2] = texture.borderColorF[2][3] = borderColor.b;
+		texture.borderColorF[3][0] = texture.borderColorF[3][1] = texture.borderColorF[3][2] = texture.borderColorF[3][3] = borderColor.a;
+	}
+
+	void Sampler::setMaxAnisotropy(unsigned int maxAnisotropy)
+	{
+		texture.maxAnisotropy = (float)maxAnisotropy;
+	}
+
+	void Sampler::setFilterQuality(FilterType maximumFilterQuality)
+	{
+		Sampler::maximumTextureFilterQuality = maximumFilterQuality;
+	}
+
+	void Sampler::setMipmapQuality(MipmapType maximumFilterQuality)
+	{
+		Sampler::maximumMipmapFilterQuality = maximumFilterQuality;
+	}
+
+	void Sampler::setMipmapLOD(float LOD)
+	{
+		texture.LOD = LOD;
+		exp2LOD = exp2(LOD);
+	}
+
+	bool Sampler::hasTexture() const
+	{
+		return textureType != TEXTURE_NULL;
+	}
+
+	bool Sampler::hasUnsignedTexture() const
+	{
+		return Surface::isUnsignedComponent(internalTextureFormat, 0) &&
+		       Surface::isUnsignedComponent(internalTextureFormat, 1) &&
+			   Surface::isUnsignedComponent(internalTextureFormat, 2) &&
+			   Surface::isUnsignedComponent(internalTextureFormat, 3);
+	}
+
+	bool Sampler::hasCubeTexture() const
+	{
+		return textureType == TEXTURE_CUBE;
+	}
+
+	bool Sampler::hasVolumeTexture() const
+	{
+		return textureType == TEXTURE_3D;
+	}
+
+	const Texture &Sampler::getTextureData()
+	{
+		return texture;
+	}
+
+	MipmapType Sampler::mipmapFilter() const
+	{
+		if(mipmapFilterState != MIPMAP_NONE)
+		{
+			for(int i = 1; i < MIPMAP_LEVELS; i++)
+			{
+				if(texture.mipmap[0].buffer[0] != texture.mipmap[i].buffer[0])
+				{
+					return mipmapFilterState;
+				}
+			}
+		}
+
+		// Only one mipmap level
+		return MIPMAP_NONE;
+	}
+
+	bool Sampler::hasNPOTTexture() const
+	{
+		if(textureType == TEXTURE_NULL)
+		{
+			return false;
+		}
+
+		return !isPow2(texture.mipmap[0].width[0]) || !isPow2(texture.mipmap[0].height[0]) || !isPow2(texture.mipmap[0].depth[0]);
+	}
+
+	TextureType Sampler::getTextureType() const
+	{
+		return textureType;
+	}
+
+	FilterType Sampler::getTextureFilter() const
+	{
+		FilterType filter = textureFilter;
+
+		if(gather && Surface::componentCount(internalTextureFormat) == 1)
+		{
+			filter = FILTER_GATHER;
+		}
+
+		if(textureType != TEXTURE_2D || texture.maxAnisotropy == 1.0f)
+		{
+			return (FilterType)min(filter, FILTER_LINEAR);
+		}
+
+		return filter;
+	}
+
+	AddressingMode Sampler::getAddressingModeU() const
+	{
+		if(hasCubeTexture())
+		{
+			return ADDRESSING_CLAMP;
+		}
+
+		return addressingModeU;
+	}
+
+	AddressingMode Sampler::getAddressingModeV() const
+	{
+		if(hasCubeTexture())
+		{
+			return ADDRESSING_CLAMP;
+		}
+
+		return addressingModeV;
+	}
+
+	AddressingMode Sampler::getAddressingModeW() const
+	{
+		if(hasCubeTexture())
+		{
+			return ADDRESSING_CLAMP;
+		}
+
+		return addressingModeW;
+	}
+}