• 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 tlsTempVertices[7];
36 
ComputeInterpFactor(float boundaryCoord0,float boundaryCoord1)37 float ComputeInterpFactor(float boundaryCoord0, float boundaryCoord1)
38 {
39     return (boundaryCoord0 / (boundaryCoord0 - boundaryCoord1));
40 }
41 
42 template<SWR_CLIPCODES ClippingPlane>
intersect(int s,int p,const float * pInPts,const float * pInAttribs,int numInAttribs,int i,float * pOutPts,float * pOutAttribs)43 inline void intersect(
44     int s,                       // index to first edge vertex v0 in pInPts.
45     int p,                       // index to second edge vertex v1 in pInPts.
46     const float *pInPts,         // array of all the input positions.
47     const float *pInAttribs,     // array of all attributes for all vertex. All the attributes for each vertex is contiguous.
48     int numInAttribs,            // number of attributes per vertex.
49     int i,                       // output index.
50     float *pOutPts,              // array of output positions. We'll write our new intersection point at i*4.
51     float *pOutAttribs)          // array of output attributes. We'll write our new attributes at i*numInAttribs.
52 {
53     float t;
54 
55     // Find the parameter of the intersection.
56     //        t = (v1.w - v1.x) / ((v2.x - v1.x) - (v2.w - v1.w)) for x = w (RIGHT) plane, etc.
57     const float *v1 = &pInPts[s*4];
58     const float *v2 = &pInPts[p*4];
59 
60     switch (ClippingPlane)
61     {
62     case FRUSTUM_LEFT:      t = ComputeInterpFactor(v1[3] + v1[0], v2[3] + v2[0]); break;
63     case FRUSTUM_RIGHT:     t = ComputeInterpFactor(v1[3] - v1[0], v2[3] - v2[0]); break;
64     case FRUSTUM_TOP:       t = ComputeInterpFactor(v1[3] + v1[1], v2[3] + v2[1]); break;
65     case FRUSTUM_BOTTOM:    t = ComputeInterpFactor(v1[3] - v1[1], v2[3] - v2[1]); break;
66     case FRUSTUM_NEAR:      t = ComputeInterpFactor(v1[2], v2[2]); break;
67     case FRUSTUM_FAR:       t = ComputeInterpFactor(v1[3] - v1[2], v2[3] - v2[2]); break;
68     default: SWR_ASSERT(false, "invalid clipping plane: %d", ClippingPlane);
69     };
70 
71 
72     const float *a1 = &pInAttribs[s*numInAttribs];
73     const float *a2 = &pInAttribs[p*numInAttribs];
74 
75     float *pOutP    = &pOutPts[i*4];
76     float *pOutA    = &pOutAttribs[i*numInAttribs];
77 
78     // Interpolate new position.
79     for(int j = 0; j < 4; ++j)
80     {
81         pOutP[j] = v1[j] + (v2[j]-v1[j])*t;
82     }
83 
84     // Interpolate Attributes
85     for(int attr = 0; attr < numInAttribs; ++attr)
86     {
87         pOutA[attr] = a1[attr] + (a2[attr]-a1[attr])*t;
88     }
89 }
90 
91 
92 // Checks whether vertex v lies inside clipping plane
93 // in homogenous coords check -w < {x,y,z} < w;
94 //
95 template<SWR_CLIPCODES ClippingPlane>
inside(const float v[4])96 inline int inside(const float v[4])
97 {
98     switch (ClippingPlane)
99     {
100     case FRUSTUM_LEFT   : return (v[0]>=-v[3]);
101     case FRUSTUM_RIGHT  : return (v[0]<= v[3]);
102     case FRUSTUM_TOP    : return (v[1]>=-v[3]);
103     case FRUSTUM_BOTTOM : return (v[1]<= v[3]);
104     case FRUSTUM_NEAR   : return (v[2]>=0.0f);
105     case FRUSTUM_FAR    : return (v[2]<= v[3]);
106     default:
107         SWR_ASSERT(false, "invalid clipping plane: %d", ClippingPlane);
108         return 0;
109     }
110 }
111 
112 
113 // Clips a polygon in homogenous coordinates to a particular clipping plane.
114 // Takes in vertices of the polygon (InPts) and the clipping plane
115 // Puts the vertices of the clipped polygon in OutPts
116 // Returns number of points in clipped polygon
117 //
118 template<SWR_CLIPCODES ClippingPlane>
ClipTriToPlane(const float * pInPts,int numInPts,const float * pInAttribs,int numInAttribs,float * pOutPts,float * pOutAttribs)119 int ClipTriToPlane( const float *pInPts, int numInPts,
120                     const float *pInAttribs, int numInAttribs,
121                     float *pOutPts, float *pOutAttribs)
122 {
123     int i=0; // index number of OutPts, # of vertices in OutPts = i div 4;
124 
125     for (int j = 0; j < numInPts; ++j)
126     {
127         int s = j;
128         int p = (j + 1) % numInPts;
129 
130         int s_in = inside<ClippingPlane>(&pInPts[s*4]);
131         int p_in = inside<ClippingPlane>(&pInPts[p*4]);
132 
133         // test if vertex is to be added to output vertices
134         if (s_in != p_in)  // edge crosses clipping plane
135         {
136             // find point of intersection
137             intersect<ClippingPlane>(s, p, pInPts, pInAttribs, numInAttribs, i, pOutPts, pOutAttribs);
138             i++;
139         }
140         if (p_in) // 2nd vertex is inside clipping volume, add it to output
141         {
142             // Copy 2nd vertex position of edge over to output.
143             for(int k = 0; k < 4; ++k)
144             {
145                 pOutPts[i*4 + k] = pInPts[p*4 + k];
146             }
147             // Copy 2nd vertex attributes of edge over to output.
148             for(int attr = 0; attr < numInAttribs; ++attr)
149             {
150                 pOutAttribs[i*numInAttribs+attr] = pInAttribs[p*numInAttribs+attr];
151             }
152             i++;
153         }
154         // edge does not cross clipping plane and vertex outside clipping volume
155         //  => do not add vertex
156     }
157     return i;
158 }
159 
160 
161 
Clip(const float * pTriangle,const float * pAttribs,int numAttribs,float * pOutTriangles,int * numVerts,float * pOutAttribs)162 void Clip(const float *pTriangle, const float *pAttribs, int numAttribs, float *pOutTriangles, int *numVerts, float *pOutAttribs)
163 {
164     // temp storage to hold at least 6 sets of vertices, the max number that can be created during clipping
165     OSALIGNSIMD(float) tempPts[6 * 4];
166     OSALIGNSIMD(float) tempAttribs[6 * KNOB_NUM_ATTRIBUTES * 4];
167 
168     // we opt to clip to viewport frustum to produce smaller triangles for rasterization precision
169     int NumOutPts = ClipTriToPlane<FRUSTUM_NEAR>(pTriangle, 3, pAttribs, numAttribs, tempPts, tempAttribs);
170     NumOutPts = ClipTriToPlane<FRUSTUM_FAR>(tempPts, NumOutPts, tempAttribs, numAttribs, pOutTriangles, pOutAttribs);
171     NumOutPts = ClipTriToPlane<FRUSTUM_LEFT>(pOutTriangles, NumOutPts, pOutAttribs, numAttribs, tempPts, tempAttribs);
172     NumOutPts = ClipTriToPlane<FRUSTUM_RIGHT>(tempPts, NumOutPts, tempAttribs, numAttribs, pOutTriangles, pOutAttribs);
173     NumOutPts = ClipTriToPlane<FRUSTUM_BOTTOM>(pOutTriangles, NumOutPts, pOutAttribs, numAttribs, tempPts, tempAttribs);
174     NumOutPts = ClipTriToPlane<FRUSTUM_TOP>(tempPts, NumOutPts, tempAttribs, numAttribs, pOutTriangles, pOutAttribs);
175 
176     SWR_ASSERT(NumOutPts <= 6);
177 
178     *numVerts = NumOutPts;
179     return;
180 }
181 
ClipTriangles(DRAW_CONTEXT * pDC,PA_STATE & pa,uint32_t workerId,simdvector prims[],uint32_t primMask,simdscalari primId,simdscalari viewportIdx)182 void ClipTriangles(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[], uint32_t primMask, simdscalari primId, simdscalari viewportIdx)
183 {
184     SWR_CONTEXT *pContext = pDC->pContext;
185     AR_BEGIN(FEClipTriangles, pDC->drawId);
186     Clipper<3> clipper(workerId, pDC);
187     clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx);
188     AR_END(FEClipTriangles, 1);
189 }
190 
ClipLines(DRAW_CONTEXT * pDC,PA_STATE & pa,uint32_t workerId,simdvector prims[],uint32_t primMask,simdscalari primId,simdscalari viewportIdx)191 void ClipLines(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[], uint32_t primMask, simdscalari primId, simdscalari viewportIdx)
192 {
193     SWR_CONTEXT *pContext = pDC->pContext;
194     AR_BEGIN(FEClipLines, pDC->drawId);
195     Clipper<2> clipper(workerId, pDC);
196     clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx);
197     AR_END(FEClipLines, 1);
198 }
ClipPoints(DRAW_CONTEXT * pDC,PA_STATE & pa,uint32_t workerId,simdvector prims[],uint32_t primMask,simdscalari primId,simdscalari viewportIdx)199 void ClipPoints(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[], uint32_t primMask, simdscalari primId, simdscalari viewportIdx)
200 {
201     SWR_CONTEXT *pContext = pDC->pContext;
202     AR_BEGIN(FEClipPoints, pDC->drawId);
203     Clipper<1> clipper(workerId, pDC);
204     clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx);
205     AR_END(FEClipPoints, 1);
206 }
207 
208