ftransform implementation

Change-Id: I8a3be46821943951e5980125ebe648c555b9cb28
Reviewed-on: https://swiftshader-review.googlesource.com/3721
Reviewed-by: Maxime Grégoire <mgregoire@google.com>
Tested-by: Maxime Grégoire <mgregoire@google.com>
diff --git a/src/OpenGL/compiler/Initialize.cpp b/src/OpenGL/compiler/Initialize.cpp
index afcd561..31a7c7f 100644
--- a/src/OpenGL/compiler/Initialize.cpp
+++ b/src/OpenGL/compiler/Initialize.cpp
@@ -123,6 +123,7 @@
     symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFaceForward, genType, "faceforward", genType, genType, genType);
     symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpReflect, genType, "reflect", genType, genType);
     symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpRefract, genType, "refract", genType, genType, float1);
+	symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFtransform, float4, "ftransform", 0);
 
 	TType *mat2 = new TType(EbtFloat, 2, 2);
 	TType *mat2x3 = new TType(EbtFloat, 2, 3);
diff --git a/src/OpenGL/compiler/OutputASM.cpp b/src/OpenGL/compiler/OutputASM.cpp
index c2a42b6..1a9a1b9 100644
--- a/src/OpenGL/compiler/OutputASM.cpp
+++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -652,6 +652,7 @@
 		case EOpFwidth:           if(visit == PostVisit) emit(sw::Shader::OPCODE_FWIDTH, result, arg); break;

 		case EOpAny:              if(visit == PostVisit) emit(sw::Shader::OPCODE_ANY, result, arg); break;

 		case EOpAll:              if(visit == PostVisit) emit(sw::Shader::OPCODE_ALL, result, arg); break;

+		case EOpFtransform:       if(visit == PostVisit) emit(sw::Shader::OPCODE_NOP, result, arg);	break;

 		case EOpTranspose:

 			if(visit == PostVisit)

 			{

@@ -1078,6 +1079,7 @@
 		case EOpFaceForward: if(visit == PostVisit) emit(sw::Shader::OPCODE_FORWARD(dim(arg[0])), result, arg[0], arg[1], arg[2]); break;

 		case EOpReflect:     if(visit == PostVisit) emit(sw::Shader::OPCODE_REFLECT(dim(arg[0])), result, arg[0], arg[1]); break;

 		case EOpRefract:     if(visit == PostVisit) emit(sw::Shader::OPCODE_REFRACT(dim(arg[0])), result, arg[0], arg[1], arg[2]); break;

+		case EOpFtransform:	 break;

 		case EOpMul:

 			if(visit == PostVisit)

 			{

diff --git a/src/OpenGL/compiler/SymbolTable.h b/src/OpenGL/compiler/SymbolTable.h
index 64c43fd..b431528 100644
--- a/src/OpenGL/compiler/SymbolTable.h
+++ b/src/OpenGL/compiler/SymbolTable.h
@@ -346,28 +346,28 @@
 
 	void insertBuiltIn(ESymbolLevel level, TOperator op, const char *ext, TType *rvalue, const char *name, TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0)
 	{
-		if(ptype1->getBasicType() == EbtGSampler2D)
+		if(ptype1 && ptype1->getBasicType() == EbtGSampler2D)
 		{
 			bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
 			insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSampler2D), ptype2, ptype3, ptype4);
 			insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISampler2D), ptype2, ptype3, ptype4);
 			insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSampler2D), ptype2, ptype3, ptype4);
 		}
-		else if(ptype1->getBasicType() == EbtGSampler3D)
+		else if(ptype1 && ptype1->getBasicType() == EbtGSampler3D)
 		{
 			bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
 			insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSampler3D), ptype2, ptype3, ptype4);
 			insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISampler3D), ptype2, ptype3, ptype4);
 			insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSampler3D), ptype2, ptype3, ptype4);
 		}
-		else if(ptype1->getBasicType() == EbtGSamplerCube)
+		else if(ptype1 && ptype1->getBasicType() == EbtGSamplerCube)
 		{
 			bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
 			insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSamplerCube), ptype2, ptype3, ptype4);
 			insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISamplerCube), ptype2, ptype3, ptype4);
 			insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSamplerCube), ptype2, ptype3, ptype4);
 		}
-		else if(ptype1->getBasicType() == EbtGSampler2DArray)
+		else if(ptype1 && ptype1->getBasicType() == EbtGSampler2DArray)
 		{
 			bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
 			insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSampler2DArray), ptype2, ptype3, ptype4);
@@ -393,8 +393,11 @@
 		{
 			TFunction *function = new TFunction(NewPoolTString(name), *rvalue, op, ext);
 
-			TParameter param1 = {0, ptype1};
-			function->addParameter(param1);
+			if(ptype1)
+			{
+				TParameter param1 = { 0, ptype1 };
+				function->addParameter(param1);
+			}
 
 			if(ptype2)
 			{
diff --git a/src/OpenGL/compiler/intermOut.cpp b/src/OpenGL/compiler/intermOut.cpp
index b190e26..467980b 100644
--- a/src/OpenGL/compiler/intermOut.cpp
+++ b/src/OpenGL/compiler/intermOut.cpp
@@ -298,6 +298,7 @@
         case EOpFaceForward:   out << "face-forward";            break;
         case EOpReflect:       out << "reflect";                 break;
         case EOpRefract:       out << "refract";                 break;
+		case EOpFtransform:    out << "ftransform";              break;
         case EOpMul:           out << "component-wise multiply"; break;
         case EOpOuterProduct:  out << "outer product";           break;
 
diff --git a/src/OpenGL/compiler/intermediate.h b/src/OpenGL/compiler/intermediate.h
index e0ca128..40a08e1 100644
--- a/src/OpenGL/compiler/intermediate.h
+++ b/src/OpenGL/compiler/intermediate.h
@@ -155,6 +155,7 @@
     EOpFaceForward,
     EOpReflect,
     EOpRefract,
+    EOpFtransform,
 
     EOpDFdx,            // Fragment only, OES_standard_derivatives extension
     EOpDFdy,            // Fragment only, OES_standard_derivatives extension