Implement broadcasting of gl_FragColor.

Bug 19353282

Change-Id: I4319ad1836de36cc4b91b04ed226f925f82013ee
Reviewed-on: https://swiftshader-review.googlesource.com/5145
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/compiler/OutputASM.cpp b/src/OpenGL/compiler/OutputASM.cpp
index 71d2442..6b1d4f7 100644
--- a/src/OpenGL/compiler/OutputASM.cpp
+++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -2545,7 +2545,7 @@
 		case EvqFrontFacing:         pixelShader->vFaceDeclared = true; return 1;

 		case EvqPointCoord:          return varyingRegister(operand);

 		case EvqFragColor:           return 0;

-		case EvqFragData:            return 0;

+		case EvqFragData:            return fragmentOutputRegister(operand);

 		case EvqFragDepth:           return 0;

 		default: UNREACHABLE(operand->getQualifier());

 		}

diff --git a/src/OpenGL/compiler/ParseHelper.cpp b/src/OpenGL/compiler/ParseHelper.cpp
index ddf0765..40fc794 100644
--- a/src/OpenGL/compiler/ParseHelper.cpp
+++ b/src/OpenGL/compiler/ParseHelper.cpp
@@ -1128,7 +1128,7 @@
 
 		// This validation is not quite correct - it's only an error to write to
 		// both FragData and FragColor. For simplicity, and because users shouldn't
-		// be rewarded for reading from undefined varaibles, return an error
+		// be rewarded for reading from undefined variables, return an error
 		// if they are both referenced, rather than assigned.
 		if(mUsesFragData && mUsesFragColor)
 		{
diff --git a/src/Shader/PixelProgram.cpp b/src/Shader/PixelProgram.cpp
index b0e47fd..c12097e 100644
--- a/src/Shader/PixelProgram.cpp
+++ b/src/Shader/PixelProgram.cpp
@@ -91,6 +91,8 @@
 			}
 		}
 
+		bool broadcastColor0 = true;
+
 		for(size_t i = 0; i < shader->getLength(); i++)
 		{
 			const Shader::Instruction *instruction = shader->getInstruction(i);
@@ -475,6 +477,8 @@
 				case Shader::PARAMETER_COLOROUT:
 					if(dst.rel.type == Shader::PARAMETER_VOID)
 					{
+						broadcastColor0 = (dst.index == 0) && broadcastColor0;
+
 						if(dst.x) { oC[dst.index].x = d.x; }
 						if(dst.y) { oC[dst.index].y = d.y; }
 						if(dst.z) { oC[dst.index].z = d.z; }
@@ -482,6 +486,7 @@
 					}
 					else
 					{
+						broadcastColor0 = false;
 						Int a = relativeAddress(dst) + dst.index;
 
 						if(dst.x) { oC[a].x = d.x; }
@@ -510,9 +515,19 @@
 			Nucleus::setInsertBlock(returnBlock);
 		}
 
-		for(int i = 0; i < RENDERTARGETS; i++)
+		if(broadcastColor0)
 		{
-			c[i] = oC[i];
+			for(int i = 0; i < RENDERTARGETS; i++)
+			{
+				c[i] = oC[0];
+			}
+		}
+		else
+		{
+			for(int i = 0; i < RENDERTARGETS; i++)
+			{
+				c[i] = oC[i];
+			}
 		}
 	}