Add the ChameleonMan PowerVR sample.

BUG=14598298

Change-Id: Id6dcaebe793cf3d3a10af571348f461023d2a9d2
Reviewed-on: https://swiftshader-review.googlesource.com/1090
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/tests/third_party/PowerVR/Tools/PVRTMisc.cpp b/tests/third_party/PowerVR/Tools/PVRTMisc.cpp
new file mode 100644
index 0000000..891d5ef
--- /dev/null
+++ b/tests/third_party/PowerVR/Tools/PVRTMisc.cpp
@@ -0,0 +1,433 @@
+/******************************************************************************
+
+ @File         PVRTMisc.cpp
+
+ @Title        PVRTMisc
+
+ @Version      
+
+ @Copyright    Copyright (c) Imagination Technologies Limited.
+
+ @Platform     ANSI compatible
+
+ @Description  Miscellaneous functions used in 3D rendering.
+
+******************************************************************************/
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+#include <math.h>
+#include "PVRTGlobal.h"
+#include "PVRTContext.h"
+#include "PVRTFixedPoint.h"
+#include "PVRTMatrix.h"
+#include "PVRTMisc.h"
+
+
+
+/*!***************************************************************************
+ @Function			PVRTMiscCalculateIntersectionLinePlane
+ @Input				pfPlane			Length 4 [A,B,C,D], values for plane
+									equation
+ @Input				pv0				A point on the line
+ @Input				pv1				Another point on the line
+ @Output			pvIntersection	The point of intersection
+ @Description		Calculates coords of the intersection of a line and an
+					infinite plane
+*****************************************************************************/
+void PVRTMiscCalculateIntersectionLinePlane(
+	PVRTVECTOR3			* const pvIntersection,
+	const VERTTYPE		pfPlane[4],
+	const PVRTVECTOR3	* const pv0,
+	const PVRTVECTOR3	* const pv1)
+{
+	PVRTVECTOR3	vD;
+	VERTTYPE fN, fD, fT;
+
+	/* Calculate vector from point0 to point1 */
+	vD.x = pv1->x - pv0->x;
+	vD.y = pv1->y - pv0->y;
+	vD.z = pv1->z - pv0->z;
+
+	/* Denominator */
+	fD =
+		VERTTYPEMUL(pfPlane[0], vD.x) +
+		VERTTYPEMUL(pfPlane[1], vD.y) +
+		VERTTYPEMUL(pfPlane[2], vD.z);
+
+	/* Numerator */
+	fN =
+		VERTTYPEMUL(pfPlane[0], pv0->x) +
+		VERTTYPEMUL(pfPlane[1], pv0->y) +
+		VERTTYPEMUL(pfPlane[2], pv0->z) +
+		pfPlane[3];
+
+	fT = VERTTYPEDIV(-fN, fD);
+
+	/* And for a finale, calculate the intersection coordinate */
+	pvIntersection->x = pv0->x + VERTTYPEMUL(fT, vD.x);
+	pvIntersection->y = pv0->y + VERTTYPEMUL(fT, vD.y);
+	pvIntersection->z = pv0->z + VERTTYPEMUL(fT, vD.z);
+}
+
+
+/*!***************************************************************************
+ @Function		PVRTMiscCalculateInfinitePlane
+ @Input			nStride			Size of each vertex structure containing pfVtx
+ @Input			pvPlane			Length 4 [A,B,C,D], values for plane equation
+ @Input			pmViewProjInv	The inverse of the View Projection matrix
+ @Input			pFrom			Position of the camera
+ @Input			fFar			Far clipping distance
+ @Output		pfVtx			Position of the first of 3 floats to receive
+								the position of vertex 0; up to 5 vertex positions
+								will be written (5 is the maximum number of vertices
+								required to draw an infinite polygon clipped to screen
+								and far clip plane).
+ @Returns		Number of vertices in the polygon fan (Can be 0, 3, 4 or 5)
+ @Description	Calculates world-space coords of a screen-filling
+				representation of an infinite plane The resulting vertices run
+				counter-clockwise around the screen, and can be simply drawn using
+				non-indexed TRIANGLEFAN
+*****************************************************************************/
+int PVRTMiscCalculateInfinitePlane(
+	VERTTYPE			* const pfVtx,
+	const int			nStride,
+	const PVRTVECTOR4	* const pvPlane,
+	const PVRTMATRIX 	* const pmViewProjInv,
+	const PVRTVECTOR3	* const pFrom,
+	const VERTTYPE		fFar)
+{
+	PVRTVECTOR3		pvWorld[5];
+	PVRTVECTOR3		*pvPolyPtr;
+	unsigned int	dwCount;
+	bool			bClip;
+	int				nVert;
+	VERTTYPE		fDotProduct;
+
+	/*
+		Check whether the plane faces the camera
+	*/
+	fDotProduct =
+		VERTTYPEMUL((pFrom->x + VERTTYPEMUL(pvPlane->x, pvPlane->w)), pvPlane->x) +
+		VERTTYPEMUL((pFrom->y + VERTTYPEMUL(pvPlane->y, pvPlane->w)), pvPlane->y) +
+		VERTTYPEMUL((pFrom->z + VERTTYPEMUL(pvPlane->z, pvPlane->w)), pvPlane->z);
+
+	if(fDotProduct < 0) {
+		/* Camera is behind plane, hence it's not visible */
+		return 0;
+	}
+
+	/*
+		Back transform front clipping plane into world space,
+		to give us a point on the line through each corner of the screen
+		(from the camera).
+	*/
+
+	/*             x = -1.0f;    y = -1.0f;     z = 1.0f;      w = 1.0f */
+	pvWorld[0].x = VERTTYPEMUL((-pmViewProjInv->f[ 0] - pmViewProjInv->f[ 4] + pmViewProjInv->f[ 8] + pmViewProjInv->f[12]), fFar);
+	pvWorld[0].y = VERTTYPEMUL((-pmViewProjInv->f[ 1] - pmViewProjInv->f[ 5] + pmViewProjInv->f[ 9] + pmViewProjInv->f[13]), fFar);
+	pvWorld[0].z = VERTTYPEMUL((-pmViewProjInv->f[ 2] - pmViewProjInv->f[ 6] + pmViewProjInv->f[10] + pmViewProjInv->f[14]), fFar);
+	/*             x =  1.0f,    y = -1.0f,     z = 1.0f;      w = 1.0f */
+	pvWorld[1].x = VERTTYPEMUL(( pmViewProjInv->f[ 0] - pmViewProjInv->f[ 4] + pmViewProjInv->f[ 8] + pmViewProjInv->f[12]), fFar);
+	pvWorld[1].y = VERTTYPEMUL(( pmViewProjInv->f[ 1] - pmViewProjInv->f[ 5] + pmViewProjInv->f[ 9] + pmViewProjInv->f[13]), fFar);
+	pvWorld[1].z = VERTTYPEMUL(( pmViewProjInv->f[ 2] - pmViewProjInv->f[ 6] + pmViewProjInv->f[10] + pmViewProjInv->f[14]), fFar);
+	/*             x =  1.0f,    y =  1.0f,     z = 1.0f;      w = 1.0f */
+	pvWorld[2].x = VERTTYPEMUL(( pmViewProjInv->f[ 0] + pmViewProjInv->f[ 4] + pmViewProjInv->f[ 8] + pmViewProjInv->f[12]), fFar);
+	pvWorld[2].y = VERTTYPEMUL(( pmViewProjInv->f[ 1] + pmViewProjInv->f[ 5] + pmViewProjInv->f[ 9] + pmViewProjInv->f[13]), fFar);
+	pvWorld[2].z = VERTTYPEMUL(( pmViewProjInv->f[ 2] + pmViewProjInv->f[ 6] + pmViewProjInv->f[10] + pmViewProjInv->f[14]), fFar);
+	/*             x = -1.0f,    y =  1.0f,     z = 1.0f;      w = 1.0f */
+	pvWorld[3].x = VERTTYPEMUL((-pmViewProjInv->f[ 0] + pmViewProjInv->f[ 4] + pmViewProjInv->f[ 8] + pmViewProjInv->f[12]), fFar);
+	pvWorld[3].y = VERTTYPEMUL((-pmViewProjInv->f[ 1] + pmViewProjInv->f[ 5] + pmViewProjInv->f[ 9] + pmViewProjInv->f[13]), fFar);
+	pvWorld[3].z = VERTTYPEMUL((-pmViewProjInv->f[ 2] + pmViewProjInv->f[ 6] + pmViewProjInv->f[10] + pmViewProjInv->f[14]), fFar);
+
+	/* We need to do a closed loop of the screen vertices, so copy the first vertex into the last */
+	pvWorld[4] = pvWorld[0];
+
+	/*
+		Now build a pre-clipped polygon
+	*/
+
+	/* Lets get ready to loop */
+	dwCount		= 0;
+	bClip		= false;
+	pvPolyPtr	= (PVRTVECTOR3*)pfVtx;
+
+	nVert = 5;
+	while(nVert)
+	{
+		nVert--;
+
+		/*
+			Check which side of the Plane this corner of the far clipping
+			plane is on. [A,B,C] of plane equation is the plane normal, D is
+			distance from origin; hence [pvPlane->x * -pvPlane->w,
+										 pvPlane->y * -pvPlane->w,
+										 pvPlane->z * -pvPlane->w]
+			is a point on the plane
+		*/
+		fDotProduct =
+			VERTTYPEMUL((pvWorld[nVert].x + VERTTYPEMUL(pvPlane->x, pvPlane->w)), pvPlane->x) +
+			VERTTYPEMUL((pvWorld[nVert].y + VERTTYPEMUL(pvPlane->y, pvPlane->w)), pvPlane->y) +
+			VERTTYPEMUL((pvWorld[nVert].z + VERTTYPEMUL(pvPlane->z, pvPlane->w)), pvPlane->z);
+
+		if(fDotProduct < 0)
+		{
+			/*
+				Behind plane; Vertex does NOT need clipping
+			*/
+			if(bClip == true)
+			{
+				/* Clipping finished */
+				bClip = false;
+
+				/*
+					We've been clipping, so we need to add an additional
+					point on the line to this point, where clipping was
+					stopped.
+				*/
+				PVRTMiscCalculateIntersectionLinePlane(pvPolyPtr, &pvPlane->x, &pvWorld[nVert+1], &pvWorld[nVert]);
+				pvPolyPtr = (PVRTVECTOR3*)((char*)pvPolyPtr + nStride);
+				dwCount++;
+			}
+
+			if(!nVert)
+			{
+				/* Abort, abort: we've closed the loop with the clipped point */
+				break;
+			}
+
+			/* Add the current point */
+			PVRTMiscCalculateIntersectionLinePlane(pvPolyPtr, &pvPlane->x, pFrom, &pvWorld[nVert]);
+			pvPolyPtr = (PVRTVECTOR3*)((char*)pvPolyPtr + nStride);
+			dwCount++;
+		}
+		else
+		{
+			/*
+				Before plane; Vertex DOES need clipping
+			*/
+			if(bClip == true)
+			{
+				/* Already in clipping, skip point */
+				continue;
+			}
+
+			/* Clipping initiated */
+			bClip = true;
+
+			/* Don't bother with entry point on first vertex; will take care of it on last vertex (which is a repeat of first vertex) */
+			if(nVert != 4)
+			{
+				/* We need to add an additional point on the line to this point, where clipping was started */
+				PVRTMiscCalculateIntersectionLinePlane(pvPolyPtr, &pvPlane->x, &pvWorld[nVert+1], &pvWorld[nVert]);
+				pvPolyPtr = (PVRTVECTOR3*)((char*)pvPolyPtr + nStride);
+				dwCount++;
+			}
+		}
+	}
+
+	/* Valid vertex counts are 0, 3, 4, 5 */
+	_ASSERT(dwCount <= 5);
+	_ASSERT(dwCount != 1);
+	_ASSERT(dwCount != 2);
+
+	return dwCount;
+}
+
+
+/*!***************************************************************************
+ @Function			SetVertex
+ @Modified			Vertices
+ @Input				index
+ @Input				x
+ @Input				y
+ @Input				z
+ @Description		Writes a vertex in a vertex array
+*****************************************************************************/
+static void SetVertex(VERTTYPE** Vertices, int index, VERTTYPE x, VERTTYPE y, VERTTYPE z)
+{
+	(*Vertices)[index*3+0] = x;
+	(*Vertices)[index*3+1] = y;
+	(*Vertices)[index*3+2] = z;
+}
+
+/*!***************************************************************************
+ @Function			SetUV
+ @Modified			UVs
+ @Input				index
+ @Input				u
+ @Input				v
+ @Description		Writes a texture coordinate in a texture coordinate array
+*****************************************************************************/
+static void SetUV(VERTTYPE** UVs, int index, VERTTYPE u, VERTTYPE v)
+{
+	(*UVs)[index*2+0] = u;
+	(*UVs)[index*2+1] = v;
+}
+
+/*!***************************************************************************
+ @Function		PVRTCreateSkybox
+ @Input			scale			Scale the skybox
+ @Input			adjustUV		Adjust or not UVs for PVRT compression
+ @Input			textureSize		Texture size in pixels
+ @Output		Vertices		Array of vertices
+ @Output		UVs				Array of UVs
+ @Description	Creates the vertices and texture coordinates for a skybox
+*****************************************************************************/
+void PVRTCreateSkybox(float scale, bool adjustUV, int textureSize, VERTTYPE** Vertices, VERTTYPE** UVs)
+{
+	*Vertices = new VERTTYPE[24*3];
+	*UVs = new VERTTYPE[24*2];
+
+	VERTTYPE unit = f2vt(1);
+	VERTTYPE a0 = 0, a1 = unit;
+
+	if (adjustUV)
+	{
+		VERTTYPE oneover = f2vt(1.0f / textureSize);
+		a0 = VERTTYPEMUL(f2vt(4.0f), oneover);
+		a1 = unit - a0;
+	}
+
+	// Front
+	SetVertex(Vertices, 0, -unit, +unit, -unit);
+	SetVertex(Vertices, 1, +unit, +unit, -unit);
+	SetVertex(Vertices, 2, -unit, -unit, -unit);
+	SetVertex(Vertices, 3, +unit, -unit, -unit);
+	SetUV(UVs, 0, a0, a1);
+	SetUV(UVs, 1, a1, a1);
+	SetUV(UVs, 2, a0, a0);
+	SetUV(UVs, 3, a1, a0);
+
+	// Right
+	SetVertex(Vertices, 4, +unit, +unit, -unit);
+	SetVertex(Vertices, 5, +unit, +unit, +unit);
+	SetVertex(Vertices, 6, +unit, -unit, -unit);
+	SetVertex(Vertices, 7, +unit, -unit, +unit);
+	SetUV(UVs, 4, a0, a1);
+	SetUV(UVs, 5, a1, a1);
+	SetUV(UVs, 6, a0, a0);
+	SetUV(UVs, 7, a1, a0);
+
+	// Back
+	SetVertex(Vertices, 8 , +unit, +unit, +unit);
+	SetVertex(Vertices, 9 , -unit, +unit, +unit);
+	SetVertex(Vertices, 10, +unit, -unit, +unit);
+	SetVertex(Vertices, 11, -unit, -unit, +unit);
+	SetUV(UVs, 8 , a0, a1);
+	SetUV(UVs, 9 , a1, a1);
+	SetUV(UVs, 10, a0, a0);
+	SetUV(UVs, 11, a1, a0);
+
+	// Left
+	SetVertex(Vertices, 12, -unit, +unit, +unit);
+	SetVertex(Vertices, 13, -unit, +unit, -unit);
+	SetVertex(Vertices, 14, -unit, -unit, +unit);
+	SetVertex(Vertices, 15, -unit, -unit, -unit);
+	SetUV(UVs, 12, a0, a1);
+	SetUV(UVs, 13, a1, a1);
+	SetUV(UVs, 14, a0, a0);
+	SetUV(UVs, 15, a1, a0);
+
+	// Top
+	SetVertex(Vertices, 16, -unit, +unit, +unit);
+	SetVertex(Vertices, 17, +unit, +unit, +unit);
+	SetVertex(Vertices, 18, -unit, +unit, -unit);
+	SetVertex(Vertices, 19, +unit, +unit, -unit);
+	SetUV(UVs, 16, a0, a1);
+	SetUV(UVs, 17, a1, a1);
+	SetUV(UVs, 18, a0, a0);
+	SetUV(UVs, 19, a1, a0);
+
+	// Bottom
+	SetVertex(Vertices, 20, -unit, -unit, -unit);
+	SetVertex(Vertices, 21, +unit, -unit, -unit);
+	SetVertex(Vertices, 22, -unit, -unit, +unit);
+	SetVertex(Vertices, 23, +unit, -unit, +unit);
+	SetUV(UVs, 20, a0, a1);
+	SetUV(UVs, 21, a1, a1);
+	SetUV(UVs, 22, a0, a0);
+	SetUV(UVs, 23, a1, a0);
+
+	for (int i=0; i<24*3; i++) (*Vertices)[i] = VERTTYPEMUL((*Vertices)[i], f2vt(scale));
+}
+
+/*!***************************************************************************
+ @Function		PVRTDestroySkybox
+ @Input			Vertices	Vertices array to destroy
+ @Input			UVs			UVs array to destroy
+ @Description	Destroy the memory allocated for a skybox
+*****************************************************************************/
+void PVRTDestroySkybox(VERTTYPE* Vertices, VERTTYPE* UVs)
+{
+	delete [] Vertices;
+	delete [] UVs;
+}
+
+/*!***************************************************************************
+ @Function		PVRTGetPOTHigher
+ @Input			uiOriginalValue	Base value
+ @Input			iTimesHigher		Multiplier
+ @Description	When iTimesHigher is one, this function will return the closest
+				power-of-two value above the base value.
+				For every increment beyond one for the iTimesHigher value,
+				the next highest power-of-two value will be calculated.
+*****************************************************************************/
+unsigned int PVRTGetPOTHigher(unsigned int uiOriginalValue, int iTimesHigher)
+{
+	if(uiOriginalValue == 0 || iTimesHigher < 0)
+	{
+		return 0;
+	}
+
+	unsigned int uiSize = 1;
+	while (uiSize < uiOriginalValue) uiSize *= 2;
+
+	// Keep increasing the POT value until the iTimesHigher value has been met
+	for(int i = 1 ; i < iTimesHigher; ++i)
+	{
+		uiSize *= 2;
+	}
+
+	return uiSize;
+}
+
+/*!***************************************************************************
+ @Function		PVRTGetPOTLower
+ @Input			uiOriginalValue	Base value
+ @Input			iTimesLower		Multiplier
+ @Description	When iTimesLower is one, this function will return the closest
+				power-of-two value below the base value.
+				For every increment beyond one for the iTimesLower value,
+				the next lowest power-of-two value will be calculated. The lowest
+				value that can be reached is 1.
+*****************************************************************************/
+// NOTE: This function should be optimised
+unsigned int PVRTGetPOTLower(unsigned int uiOriginalValue, int iTimesLower)
+{
+	if(uiOriginalValue == 0 || iTimesLower < 0)
+	{
+		return 0;
+	}
+	unsigned int uiSize = PVRTGetPOTHigher(uiOriginalValue,1);
+	uiSize >>= 1;//uiSize /=2;
+
+	for(int i = 1; i < iTimesLower; ++i)
+	{
+		uiSize >>= 1;//uiSize /=2;
+		if(uiSize == 1)
+		{
+			// Lowest possible value has been reached, so break
+			break;
+		}
+	}
+	return uiSize;
+}
+
+
+
+/*****************************************************************************
+ End of file (PVRTMisc.cpp)
+*****************************************************************************/
+