1 /**************************************************************************** 2 * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 * 23 * @file clip.cpp 24 * 25 * @brief Implementation for clipping 26 * 27 ******************************************************************************/ 28 29 #include <assert.h> 30 31 #include "common/os.h" 32 #include "core/clip.h" 33 34 // Temp storage used by the clipper 35 THREAD SIMDVERTEX_T<SIMD256> tlsTempVertices[7]; 36 #if USE_SIMD16_FRONTEND 37 THREAD SIMDVERTEX_T<SIMD512> tlsTempVertices_simd16[7]; 38 #endif 39 40 float ComputeInterpFactor(float boundaryCoord0, float boundaryCoord1) 41 { 42 return (boundaryCoord0 / (boundaryCoord0 - boundaryCoord1)); 43 } 44 45 template<SWR_CLIPCODES ClippingPlane> 46 inline void intersect( 47 int s, // index to first edge vertex v0 in pInPts. 48 int p, // index to second edge vertex v1 in pInPts. 49 const float *pInPts, // array of all the input positions. 50 const float *pInAttribs, // array of all attributes for all vertex. All the attributes for each vertex is contiguous. 51 int numInAttribs, // number of attributes per vertex. 52 int i, // output index. 53 float *pOutPts, // array of output positions. We'll write our new intersection point at i*4. 54 float *pOutAttribs) // array of output attributes. We'll write our new attributes at i*numInAttribs. 55 { 56 float t; 57 58 // Find the parameter of the intersection. 59 // t = (v1.w - v1.x) / ((v2.x - v1.x) - (v2.w - v1.w)) for x = w (RIGHT) plane, etc. 60 const float *v1 = &pInPts[s*4]; 61 const float *v2 = &pInPts[p*4]; 62 63 switch (ClippingPlane) 64 { 65 case FRUSTUM_LEFT: t = ComputeInterpFactor(v1[3] + v1[0], v2[3] + v2[0]); break; 66 case FRUSTUM_RIGHT: t = ComputeInterpFactor(v1[3] - v1[0], v2[3] - v2[0]); break; 67 case FRUSTUM_TOP: t = ComputeInterpFactor(v1[3] + v1[1], v2[3] + v2[1]); break; 68 case FRUSTUM_BOTTOM: t = ComputeInterpFactor(v1[3] - v1[1], v2[3] - v2[1]); break; 69 case FRUSTUM_NEAR: t = ComputeInterpFactor(v1[2], v2[2]); break; 70 case FRUSTUM_FAR: t = ComputeInterpFactor(v1[3] - v1[2], v2[3] - v2[2]); break; 71 default: SWR_INVALID("invalid clipping plane: %d", ClippingPlane); 72 }; 73 74 75 const float *a1 = &pInAttribs[s*numInAttribs]; 76 const float *a2 = &pInAttribs[p*numInAttribs]; 77 78 float *pOutP = &pOutPts[i*4]; 79 float *pOutA = &pOutAttribs[i*numInAttribs]; 80 81 // Interpolate new position. 82 for(int j = 0; j < 4; ++j) 83 { 84 pOutP[j] = v1[j] + (v2[j]-v1[j])*t; 85 } 86 87 // Interpolate Attributes 88 for(int attr = 0; attr < numInAttribs; ++attr) 89 { 90 pOutA[attr] = a1[attr] + (a2[attr]-a1[attr])*t; 91 } 92 } 93 94 95 // Checks whether vertex v lies inside clipping plane 96 // in homogenous coords check -w < {x,y,z} < w; 97 // 98 template<SWR_CLIPCODES ClippingPlane> 99 inline int inside(const float v[4]) 100 { 101 switch (ClippingPlane) 102 { 103 case FRUSTUM_LEFT : return (v[0]>=-v[3]); 104 case FRUSTUM_RIGHT : return (v[0]<= v[3]); 105 case FRUSTUM_TOP : return (v[1]>=-v[3]); 106 case FRUSTUM_BOTTOM : return (v[1]<= v[3]); 107 case FRUSTUM_NEAR : return (v[2]>=0.0f); 108 case FRUSTUM_FAR : return (v[2]<= v[3]); 109 default: 110 SWR_INVALID("invalid clipping plane: %d", ClippingPlane); 111 return 0; 112 } 113 } 114 115 116 // Clips a polygon in homogenous coordinates to a particular clipping plane. 117 // Takes in vertices of the polygon (InPts) and the clipping plane 118 // Puts the vertices of the clipped polygon in OutPts 119 // Returns number of points in clipped polygon 120 // 121 template<SWR_CLIPCODES ClippingPlane> 122 int ClipTriToPlane( const float *pInPts, int numInPts, 123 const float *pInAttribs, int numInAttribs, 124 float *pOutPts, float *pOutAttribs) 125 { 126 int i=0; // index number of OutPts, # of vertices in OutPts = i div 4; 127 128 for (int j = 0; j < numInPts; ++j) 129 { 130 int s = j; 131 int p = (j + 1) % numInPts; 132 133 int s_in = inside<ClippingPlane>(&pInPts[s*4]); 134 int p_in = inside<ClippingPlane>(&pInPts[p*4]); 135 136 // test if vertex is to be added to output vertices 137 if (s_in != p_in) // edge crosses clipping plane 138 { 139 // find point of intersection 140 intersect<ClippingPlane>(s, p, pInPts, pInAttribs, numInAttribs, i, pOutPts, pOutAttribs); 141 i++; 142 } 143 if (p_in) // 2nd vertex is inside clipping volume, add it to output 144 { 145 // Copy 2nd vertex position of edge over to output. 146 for(int k = 0; k < 4; ++k) 147 { 148 pOutPts[i*4 + k] = pInPts[p*4 + k]; 149 } 150 // Copy 2nd vertex attributes of edge over to output. 151 for(int attr = 0; attr < numInAttribs; ++attr) 152 { 153 pOutAttribs[i*numInAttribs+attr] = pInAttribs[p*numInAttribs+attr]; 154 } 155 i++; 156 } 157 // edge does not cross clipping plane and vertex outside clipping volume 158 // => do not add vertex 159 } 160 return i; 161 } 162 163 void ClipTriangles(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[], uint32_t primMask, 164 simdscalari const &primId, simdscalari const &viewportIdx, simdscalari const &rtIdx) 165 { 166 SWR_CONTEXT *pContext = pDC->pContext; 167 AR_BEGIN(FEClipTriangles, pDC->drawId); 168 Clipper<SIMD256, 3> clipper(workerId, pDC); 169 clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx); 170 AR_END(FEClipTriangles, 1); 171 } 172 173 void ClipLines(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[], uint32_t primMask, 174 simdscalari const &primId, simdscalari const &viewportIdx, simdscalari const &rtIdx) 175 { 176 SWR_CONTEXT *pContext = pDC->pContext; 177 AR_BEGIN(FEClipLines, pDC->drawId); 178 Clipper<SIMD256, 2> clipper(workerId, pDC); 179 clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx); 180 AR_END(FEClipLines, 1); 181 } 182 183 void ClipPoints(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[], uint32_t primMask, 184 simdscalari const &primId, simdscalari const &viewportIdx, simdscalari const &rtIdx) 185 { 186 SWR_CONTEXT *pContext = pDC->pContext; 187 AR_BEGIN(FEClipPoints, pDC->drawId); 188 Clipper<SIMD256, 1> clipper(workerId, pDC); 189 clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx); 190 AR_END(FEClipPoints, 1); 191 } 192 193 #if USE_SIMD16_FRONTEND 194 void SIMDCALL ClipTriangles_simd16(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simd16vector prims[], uint32_t primMask, 195 simd16scalari const &primId, simd16scalari const &viewportIdx, simd16scalari const &rtIdx) 196 { 197 SWR_CONTEXT *pContext = pDC->pContext; 198 AR_BEGIN(FEClipTriangles, pDC->drawId); 199 200 enum { VERTS_PER_PRIM = 3 }; 201 202 Clipper<SIMD512, VERTS_PER_PRIM> clipper(workerId, pDC); 203 204 pa.useAlternateOffset = false; 205 clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx); 206 207 AR_END(FEClipTriangles, 1); 208 } 209 210 void SIMDCALL ClipLines_simd16(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simd16vector prims[], uint32_t primMask, 211 simd16scalari const &primId, simd16scalari const &viewportIdx, simd16scalari const &rtIdx) 212 { 213 SWR_CONTEXT *pContext = pDC->pContext; 214 AR_BEGIN(FEClipLines, pDC->drawId); 215 216 enum { VERTS_PER_PRIM = 2 }; 217 218 Clipper<SIMD512, VERTS_PER_PRIM> clipper(workerId, pDC); 219 220 pa.useAlternateOffset = false; 221 clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx); 222 223 AR_END(FEClipLines, 1); 224 } 225 226 void SIMDCALL ClipPoints_simd16(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simd16vector prims[], uint32_t primMask, 227 simd16scalari const &primId, simd16scalari const &viewportIdx, simd16scalari const &rtIdx) 228 { 229 SWR_CONTEXT *pContext = pDC->pContext; 230 AR_BEGIN(FEClipPoints, pDC->drawId); 231 232 enum { VERTS_PER_PRIM = 1 }; 233 234 Clipper<SIMD512, VERTS_PER_PRIM> clipper(workerId, pDC); 235 236 pa.useAlternateOffset = false; 237 clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx); 238 239 AR_END(FEClipPoints, 1); 240 } 241 242 #endif 243