• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ComputeInterpFactor(float boundaryCoord0,float boundaryCoord1)40 float ComputeInterpFactor(float boundaryCoord0, float boundaryCoord1)
41 {
42     return (boundaryCoord0 / (boundaryCoord0 - boundaryCoord1));
43 }
44 
45 template<SWR_CLIPCODES ClippingPlane>
intersect(int s,int p,const float * pInPts,const float * pInAttribs,int numInAttribs,int i,float * pOutPts,float * pOutAttribs)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>
inside(const float v[4])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>
ClipTriToPlane(const float * pInPts,int numInPts,const float * pInAttribs,int numInAttribs,float * pOutPts,float * pOutAttribs)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 
ClipTriangles(DRAW_CONTEXT * pDC,PA_STATE & pa,uint32_t workerId,simdvector prims[],uint32_t primMask,simdscalari const & primId,simdscalari const & viewportIdx,simdscalari const & rtIdx)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 
ClipLines(DRAW_CONTEXT * pDC,PA_STATE & pa,uint32_t workerId,simdvector prims[],uint32_t primMask,simdscalari const & primId,simdscalari const & viewportIdx,simdscalari const & rtIdx)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 
ClipPoints(DRAW_CONTEXT * pDC,PA_STATE & pa,uint32_t workerId,simdvector prims[],uint32_t primMask,simdscalari const & primId,simdscalari const & viewportIdx,simdscalari const & rtIdx)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
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)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 
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)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 
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)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