Implement OpenGL single-color specular lighting.

Change-Id: I40f9ad720bdbd93c44be8fb991dfbf055a3eceba
Reviewed-on: https://swiftshader-review.googlesource.com/3803
Reviewed-by: Nicolas Capens <capn@google.com>
Tested-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libGLES_CM/Device.cpp b/src/OpenGL/libGLES_CM/Device.cpp
index bc2121f..ebe6cc6 100644
--- a/src/OpenGL/libGLES_CM/Device.cpp
+++ b/src/OpenGL/libGLES_CM/Device.cpp
@@ -47,7 +47,8 @@
 		setAlphaCompare(ALPHA_ALWAYS);

 		setAlphaBlendEnable(false);

 		setFogEnable(false);

-		setSpecularEnable(false);

+		setSpecularEnable(true);

+		setLocalViewer(false);

 		setFogColor(0);

 		setPixelFogMode(FOG_NONE);

 		setFogStart(0.0f);

diff --git a/src/Renderer/Context.cpp b/src/Renderer/Context.cpp
index fd8a307..ce43d9b 100644
--- a/src/Renderer/Context.cpp
+++ b/src/Renderer/Context.cpp
@@ -31,6 +31,7 @@
 	bool booleanFaceRegister = false;
 	bool fullPixelPositionRegister = false;
 	bool leadingVertexFirst = false;         // Flat shading uses first vertex, else last
+	bool secondaryColor = false;             // Specular lighting is applied after texturing
 
 	bool forceWindowed = false;
 	bool quadLayoutEnabled = false;
diff --git a/src/Renderer/Renderer.cpp b/src/Renderer/Renderer.cpp
index c2abe55..197802f 100644
--- a/src/Renderer/Renderer.cpp
+++ b/src/Renderer/Renderer.cpp
@@ -45,12 +45,13 @@
 	extern bool symmetricNormalizedDepth;   // [-1, 1] instead of [0, 1]
 	extern bool booleanFaceRegister;
 	extern bool fullPixelPositionRegister;
+	extern bool leadingVertexFirst;         // Flat shading uses first vertex, else last
+	extern bool secondaryColor;             // Specular lighting is applied after texturing
 
 	extern bool forceWindowed;
 	extern bool complementaryDepthBuffer;
 	extern bool postBlendSRGB;
 	extern bool exactColorRounding;
-	extern bool leadingVertexFirst;
 	extern TransparencyAntialiasing transparencyAntialiasing;
 	extern bool forceClearRegisters;
 
@@ -107,6 +108,7 @@
 		sw::booleanFaceRegister = conventions.booleanFaceRegister;
 		sw::fullPixelPositionRegister = conventions.fullPixelPositionRegister;
 		sw::leadingVertexFirst = conventions.leadingVertexFirst;
+		sw::secondaryColor = conventions.secondaryColor;
 		sw::exactColorRounding = exactColorRounding;
 
 		setRenderTarget(0, 0);
diff --git a/src/Renderer/Renderer.hpp b/src/Renderer/Renderer.hpp
index c58e273..235fc1c 100644
--- a/src/Renderer/Renderer.hpp
+++ b/src/Renderer/Renderer.hpp
@@ -61,15 +61,17 @@
 		bool booleanFaceRegister;
 		bool fullPixelPositionRegister;
 		bool leadingVertexFirst;
+		bool secondaryColor;
 	};
 
 	static const Conventions OpenGL =
 	{
-		true,   // halfIntegerCoordinates
-		true,   // symmetricNormalizedDepth
-		true,   // booleanFaceRegister
-		true,   // fullPixelPositionRegister
-		false   // leadingVertexFirst
+		true,    // halfIntegerCoordinates
+		true,    // symmetricNormalizedDepth
+		true,    // booleanFaceRegister
+		true,    // fullPixelPositionRegister
+		false,   // leadingVertexFirst
+		false    // secondaryColor
 	};
 
 	static const Conventions Direct3D =
@@ -78,7 +80,8 @@
 		false,   // symmetricNormalizedDepth
 		false,   // booleanFaceRegister
 		false,   // fullPixelPositionRegister
-		true     // leadingVertexFirst
+		true,    // leadingVertexFirst
+		true,    // secondardyColor
 	};
 
 	struct Query
diff --git a/src/Shader/VertexPipeline.cpp b/src/Shader/VertexPipeline.cpp
index f54852f..dd5f82e 100644
--- a/src/Shader/VertexPipeline.cpp
+++ b/src/Shader/VertexPipeline.cpp
@@ -24,6 +24,8 @@
 
 namespace sw
 {
+	extern bool secondaryColor;
+
 	VertexPipeline::VertexPipeline(const VertexProcessor::State &state) : VertexRoutine(state, 0)
 	{
 	}
@@ -379,9 +381,18 @@
 					spec.y = Max(spec.y, Float4(0.0f));
 					spec.z = Max(spec.z, Float4(0.0f));
 
-					r.o[D1].x = r.o[D1].x + spec.x;
-					r.o[D1].y = r.o[D1].y + spec.y;
-					r.o[D1].z = r.o[D1].z + spec.z;
+					if(secondaryColor)
+					{
+						r.o[D1].x = r.o[D1].x + spec.x;
+						r.o[D1].y = r.o[D1].y + spec.y;
+						r.o[D1].z = r.o[D1].z + spec.z;
+					}
+					else
+					{
+						r.o[D0].x = r.o[D0].x + spec.x;
+						r.o[D0].y = r.o[D0].y + spec.y;
+						r.o[D0].z = r.o[D0].z + spec.z;
+					}
 				}
 			}