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) +*****************************************************************************/ +