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 
ComputeInterpFactor(float boundaryCoord0,float boundaryCoord1)34 float ComputeInterpFactor(float boundaryCoord0, float boundaryCoord1)
35 {
36     return (boundaryCoord0 / (boundaryCoord0 - boundaryCoord1));
37 }
38 
39 template <SWR_CLIPCODES ClippingPlane>
intersect(int s,int p,const float * pInPts,const float * pInAttribs,int numInAttribs,int i,float * pOutPts,float * pOutAttribs)40 inline void intersect(
41     int          s,          // index to first edge vertex v0 in pInPts.
42     int          p,          // index to second edge vertex v1 in pInPts.
43     const float* pInPts,     // array of all the input positions.
44     const float* pInAttribs, // array of all attributes for all vertex. All the attributes for each
45                              // vertex is contiguous.
46     int    numInAttribs,     // number of attributes per vertex.
47     int    i,                // output index.
48     float* pOutPts,     // array of output positions. We'll write our new intersection point at i*4.
49     float* pOutAttribs) // array of output attributes. We'll write our new attributes at
50                         // i*numInAttribs.
51 {
52     float t;
53 
54     // Find the parameter of the intersection.
55     //        t = (v1.w - v1.x) / ((v2.x - v1.x) - (v2.w - v1.w)) for x = w (RIGHT) plane, etc.
56     const float* v1 = &pInPts[s * 4];
57     const float* v2 = &pInPts[p * 4];
58 
59     switch (ClippingPlane)
60     {
61     case FRUSTUM_LEFT:
62         t = ComputeInterpFactor(v1[3] + v1[0], v2[3] + v2[0]);
63         break;
64     case FRUSTUM_RIGHT:
65         t = ComputeInterpFactor(v1[3] - v1[0], v2[3] - v2[0]);
66         break;
67     case FRUSTUM_TOP:
68         t = ComputeInterpFactor(v1[3] + v1[1], v2[3] + v2[1]);
69         break;
70     case FRUSTUM_BOTTOM:
71         t = ComputeInterpFactor(v1[3] - v1[1], v2[3] - v2[1]);
72         break;
73     case FRUSTUM_NEAR:
74         t = ComputeInterpFactor(v1[2], v2[2]);
75         break;
76     case FRUSTUM_FAR:
77         t = ComputeInterpFactor(v1[3] - v1[2], v2[3] - v2[2]);
78         break;
79     default:
80         SWR_INVALID("invalid clipping plane: %d", ClippingPlane);
81     };
82 
83     const float* a1 = &pInAttribs[s * numInAttribs];
84     const float* a2 = &pInAttribs[p * numInAttribs];
85 
86     float* pOutP = &pOutPts[i * 4];
87     float* pOutA = &pOutAttribs[i * numInAttribs];
88 
89     // Interpolate new position.
90     for (int j = 0; j < 4; ++j)
91     {
92         pOutP[j] = v1[j] + (v2[j] - v1[j]) * t;
93     }
94 
95     // Interpolate Attributes
96     for (int attr = 0; attr < numInAttribs; ++attr)
97     {
98         pOutA[attr] = a1[attr] + (a2[attr] - a1[attr]) * t;
99     }
100 }
101 
102 // Checks whether vertex v lies inside clipping plane
103 // in homogenous coords check -w < {x,y,z} < w;
104 //
105 template <SWR_CLIPCODES ClippingPlane>
inside(const float v[4])106 inline int inside(const float v[4])
107 {
108     switch (ClippingPlane)
109     {
110     case FRUSTUM_LEFT:
111         return (v[0] >= -v[3]);
112     case FRUSTUM_RIGHT:
113         return (v[0] <= v[3]);
114     case FRUSTUM_TOP:
115         return (v[1] >= -v[3]);
116     case FRUSTUM_BOTTOM:
117         return (v[1] <= v[3]);
118     case FRUSTUM_NEAR:
119         return (v[2] >= 0.0f);
120     case FRUSTUM_FAR:
121         return (v[2] <= v[3]);
122     default:
123         SWR_INVALID("invalid clipping plane: %d", ClippingPlane);
124         return 0;
125     }
126 }
127 
128 // Clips a polygon in homogenous coordinates to a particular clipping plane.
129 // Takes in vertices of the polygon (InPts) and the clipping plane
130 // Puts the vertices of the clipped polygon in OutPts
131 // Returns number of points in clipped polygon
132 //
133 template <SWR_CLIPCODES ClippingPlane>
ClipTriToPlane(const float * pInPts,int numInPts,const float * pInAttribs,int numInAttribs,float * pOutPts,float * pOutAttribs)134 int ClipTriToPlane(const float* pInPts,
135                    int          numInPts,
136                    const float* pInAttribs,
137                    int          numInAttribs,
138                    float*       pOutPts,
139                    float*       pOutAttribs)
140 {
141     int i = 0; // index number of OutPts, # of vertices in OutPts = i div 4;
142 
143     for (int j = 0; j < numInPts; ++j)
144     {
145         int s = j;
146         int p = (j + 1) % numInPts;
147 
148         int s_in = inside<ClippingPlane>(&pInPts[s * 4]);
149         int p_in = inside<ClippingPlane>(&pInPts[p * 4]);
150 
151         // test if vertex is to be added to output vertices
152         if (s_in != p_in) // edge crosses clipping plane
153         {
154             // find point of intersection
155             intersect<ClippingPlane>(
156                 s, p, pInPts, pInAttribs, numInAttribs, i, pOutPts, pOutAttribs);
157             i++;
158         }
159         if (p_in) // 2nd vertex is inside clipping volume, add it to output
160         {
161             // Copy 2nd vertex position of edge over to output.
162             for (int k = 0; k < 4; ++k)
163             {
164                 pOutPts[i * 4 + k] = pInPts[p * 4 + k];
165             }
166             // Copy 2nd vertex attributes of edge over to output.
167             for (int attr = 0; attr < numInAttribs; ++attr)
168             {
169                 pOutAttribs[i * numInAttribs + attr] = pInAttribs[p * numInAttribs + attr];
170             }
171             i++;
172         }
173         // edge does not cross clipping plane and vertex outside clipping volume
174         //  => do not add vertex
175     }
176     return i;
177 }
178 
ClipRectangles(DRAW_CONTEXT * pDC,PA_STATE & pa,uint32_t workerId,simdvector prims[],uint32_t primMask,simdscalari const & primId,simdscalari const & viewportIdx,simdscalari const & rtIdx)179 void ClipRectangles(DRAW_CONTEXT*      pDC,
180                     PA_STATE&          pa,
181                     uint32_t           workerId,
182                     simdvector         prims[],
183                     uint32_t           primMask,
184                     simdscalari const& primId,
185                     simdscalari const& viewportIdx,
186                     simdscalari const& rtIdx)
187 {
188     RDTSC_BEGIN(pDC->pContext->pBucketMgr, FEClipRectangles, pDC->drawId);
189     Clipper<SIMD256, 3> clipper(workerId, pDC);
190     clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx);
191     RDTSC_END(pDC->pContext->pBucketMgr, FEClipRectangles, 1);
192 }
193 
ClipTriangles(DRAW_CONTEXT * pDC,PA_STATE & pa,uint32_t workerId,simdvector prims[],uint32_t primMask,simdscalari const & primId,simdscalari const & viewportIdx,simdscalari const & rtIdx)194 void ClipTriangles(DRAW_CONTEXT*      pDC,
195                    PA_STATE&          pa,
196                    uint32_t           workerId,
197                    simdvector         prims[],
198                    uint32_t           primMask,
199                    simdscalari const& primId,
200                    simdscalari const& viewportIdx,
201                    simdscalari const& rtIdx)
202 {
203     RDTSC_BEGIN(pDC->pContext->pBucketMgr, FEClipTriangles, pDC->drawId);
204     Clipper<SIMD256, 3> clipper(workerId, pDC);
205     clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx);
206     RDTSC_END(pDC->pContext->pBucketMgr, FEClipTriangles, 1);
207 }
208 
ClipLines(DRAW_CONTEXT * pDC,PA_STATE & pa,uint32_t workerId,simdvector prims[],uint32_t primMask,simdscalari const & primId,simdscalari const & viewportIdx,simdscalari const & rtIdx)209 void ClipLines(DRAW_CONTEXT*      pDC,
210                PA_STATE&          pa,
211                uint32_t           workerId,
212                simdvector         prims[],
213                uint32_t           primMask,
214                simdscalari const& primId,
215                simdscalari const& viewportIdx,
216                simdscalari const& rtIdx)
217 {
218     RDTSC_BEGIN(pDC->pContext->pBucketMgr, FEClipLines, pDC->drawId);
219     Clipper<SIMD256, 2> clipper(workerId, pDC);
220     clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx);
221     RDTSC_END(pDC->pContext->pBucketMgr, FEClipLines, 1);
222 }
223 
ClipPoints(DRAW_CONTEXT * pDC,PA_STATE & pa,uint32_t workerId,simdvector prims[],uint32_t primMask,simdscalari const & primId,simdscalari const & viewportIdx,simdscalari const & rtIdx)224 void ClipPoints(DRAW_CONTEXT*      pDC,
225                 PA_STATE&          pa,
226                 uint32_t           workerId,
227                 simdvector         prims[],
228                 uint32_t           primMask,
229                 simdscalari const& primId,
230                 simdscalari const& viewportIdx,
231                 simdscalari const& rtIdx)
232 {
233     RDTSC_BEGIN(pDC->pContext->pBucketMgr, FEClipPoints, pDC->drawId);
234     Clipper<SIMD256, 1> clipper(workerId, pDC);
235     clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx);
236     RDTSC_END(pDC->pContext->pBucketMgr, FEClipPoints, 1);
237 }
238 
239 #if USE_SIMD16_FRONTEND
ClipRectangles_simd16(DRAW_CONTEXT * pDC,PA_STATE & pa,uint32_t workerId,simd16vector prims[],uint32_t primMask,simd16scalari const & primId,simd16scalari const & viewportIdx,simd16scalari const & rtIdx)240 void SIMDCALL ClipRectangles_simd16(DRAW_CONTEXT*        pDC,
241                                     PA_STATE&            pa,
242                                     uint32_t             workerId,
243                                     simd16vector         prims[],
244                                     uint32_t             primMask,
245                                     simd16scalari const& primId,
246                                     simd16scalari const& viewportIdx,
247                                     simd16scalari const& rtIdx)
248 {
249     RDTSC_BEGIN(pDC->pContext->pBucketMgr, FEClipRectangles, pDC->drawId);
250 
251     enum
252     {
253         VERTS_PER_PRIM = 3
254     };
255 
256     Clipper<SIMD512, VERTS_PER_PRIM> clipper(workerId, pDC);
257 
258     pa.useAlternateOffset = false;
259     clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx);
260 
261     RDTSC_END(pDC->pContext->pBucketMgr, FEClipRectangles, 1);
262 }
263 
ClipTriangles_simd16(DRAW_CONTEXT * pDC,PA_STATE & pa,uint32_t workerId,simd16vector prims[],uint32_t primMask,simd16scalari const & primId,simd16scalari const & viewportIdx,simd16scalari const & rtIdx)264 void SIMDCALL ClipTriangles_simd16(DRAW_CONTEXT*        pDC,
265                                    PA_STATE&            pa,
266                                    uint32_t             workerId,
267                                    simd16vector         prims[],
268                                    uint32_t             primMask,
269                                    simd16scalari const& primId,
270                                    simd16scalari const& viewportIdx,
271                                    simd16scalari const& rtIdx)
272 {
273     RDTSC_BEGIN(pDC->pContext->pBucketMgr, FEClipTriangles, pDC->drawId);
274 
275     enum
276     {
277         VERTS_PER_PRIM = 3
278     };
279 
280     Clipper<SIMD512, VERTS_PER_PRIM> clipper(workerId, pDC);
281 
282     pa.useAlternateOffset = false;
283     clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx);
284 
285     RDTSC_END(pDC->pContext->pBucketMgr, FEClipTriangles, 1);
286 }
287 
ClipLines_simd16(DRAW_CONTEXT * pDC,PA_STATE & pa,uint32_t workerId,simd16vector prims[],uint32_t primMask,simd16scalari const & primId,simd16scalari const & viewportIdx,simd16scalari const & rtIdx)288 void SIMDCALL ClipLines_simd16(DRAW_CONTEXT*        pDC,
289                                PA_STATE&            pa,
290                                uint32_t             workerId,
291                                simd16vector         prims[],
292                                uint32_t             primMask,
293                                simd16scalari const& primId,
294                                simd16scalari const& viewportIdx,
295                                simd16scalari const& rtIdx)
296 {
297     RDTSC_BEGIN(pDC->pContext->pBucketMgr, FEClipLines, pDC->drawId);
298 
299     enum
300     {
301         VERTS_PER_PRIM = 2
302     };
303 
304     Clipper<SIMD512, VERTS_PER_PRIM> clipper(workerId, pDC);
305 
306     pa.useAlternateOffset = false;
307     clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx);
308 
309     RDTSC_END(pDC->pContext->pBucketMgr, FEClipLines, 1);
310 }
311 
ClipPoints_simd16(DRAW_CONTEXT * pDC,PA_STATE & pa,uint32_t workerId,simd16vector prims[],uint32_t primMask,simd16scalari const & primId,simd16scalari const & viewportIdx,simd16scalari const & rtIdx)312 void SIMDCALL ClipPoints_simd16(DRAW_CONTEXT*        pDC,
313                                 PA_STATE&            pa,
314                                 uint32_t             workerId,
315                                 simd16vector         prims[],
316                                 uint32_t             primMask,
317                                 simd16scalari const& primId,
318                                 simd16scalari const& viewportIdx,
319                                 simd16scalari const& rtIdx)
320 {
321     RDTSC_BEGIN(pDC->pContext->pBucketMgr, FEClipPoints, pDC->drawId);
322 
323     enum
324     {
325         VERTS_PER_PRIM = 1
326     };
327 
328     Clipper<SIMD512, VERTS_PER_PRIM> clipper(workerId, pDC);
329 
330     pa.useAlternateOffset = false;
331     clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx);
332 
333     RDTSC_END(pDC->pContext->pBucketMgr, FEClipPoints, 1);
334 }
335 
336 #endif
337