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