1 /****************************************************************************
2 * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved.
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:
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
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
25 * @brief Implementation for clipping
27 ******************************************************************************/
31 #include "common/os.h"
32 #include "core/clip.h"
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];
40 float ComputeInterpFactor(float boundaryCoord0
, float boundaryCoord1
)
42 return (boundaryCoord0
/ (boundaryCoord0
- boundaryCoord1
));
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.
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];
63 switch (ClippingPlane
)
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
);
75 const float *a1
= &pInAttribs
[s
*numInAttribs
];
76 const float *a2
= &pInAttribs
[p
*numInAttribs
];
78 float *pOutP
= &pOutPts
[i
*4];
79 float *pOutA
= &pOutAttribs
[i
*numInAttribs
];
81 // Interpolate new position.
82 for(int j
= 0; j
< 4; ++j
)
84 pOutP
[j
] = v1
[j
] + (v2
[j
]-v1
[j
])*t
;
87 // Interpolate Attributes
88 for(int attr
= 0; attr
< numInAttribs
; ++attr
)
90 pOutA
[attr
] = a1
[attr
] + (a2
[attr
]-a1
[attr
])*t
;
95 // Checks whether vertex v lies inside clipping plane
96 // in homogenous coords check -w < {x,y,z} < w;
98 template<SWR_CLIPCODES ClippingPlane
>
99 inline int inside(const float v
[4])
101 switch (ClippingPlane
)
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]);
110 SWR_INVALID("invalid clipping plane: %d", ClippingPlane
);
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
121 template<SWR_CLIPCODES ClippingPlane
>
122 int ClipTriToPlane( const float *pInPts
, int numInPts
,
123 const float *pInAttribs
, int numInAttribs
,
124 float *pOutPts
, float *pOutAttribs
)
126 int i
=0; // index number of OutPts, # of vertices in OutPts = i div 4;
128 for (int j
= 0; j
< numInPts
; ++j
)
131 int p
= (j
+ 1) % numInPts
;
133 int s_in
= inside
<ClippingPlane
>(&pInPts
[s
*4]);
134 int p_in
= inside
<ClippingPlane
>(&pInPts
[p
*4]);
136 // test if vertex is to be added to output vertices
137 if (s_in
!= p_in
) // edge crosses clipping plane
139 // find point of intersection
140 intersect
<ClippingPlane
>(s
, p
, pInPts
, pInAttribs
, numInAttribs
, i
, pOutPts
, pOutAttribs
);
143 if (p_in
) // 2nd vertex is inside clipping volume, add it to output
145 // Copy 2nd vertex position of edge over to output.
146 for(int k
= 0; k
< 4; ++k
)
148 pOutPts
[i
*4 + k
] = pInPts
[p
*4 + k
];
150 // Copy 2nd vertex attributes of edge over to output.
151 for(int attr
= 0; attr
< numInAttribs
; ++attr
)
153 pOutAttribs
[i
*numInAttribs
+attr
] = pInAttribs
[p
*numInAttribs
+attr
];
157 // edge does not cross clipping plane and vertex outside clipping volume
158 // => do not add vertex
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
)
166 SWR_CONTEXT
*pContext
= pDC
->pContext
;
167 RDTSC_BEGIN(FEClipTriangles
, pDC
->drawId
);
168 Clipper
<SIMD256
, 3> clipper(workerId
, pDC
);
169 clipper
.ExecuteStage(pa
, prims
, primMask
, primId
, viewportIdx
, rtIdx
);
170 RDTSC_END(FEClipTriangles
, 1);
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
)
176 SWR_CONTEXT
*pContext
= pDC
->pContext
;
177 RDTSC_BEGIN(FEClipLines
, pDC
->drawId
);
178 Clipper
<SIMD256
, 2> clipper(workerId
, pDC
);
179 clipper
.ExecuteStage(pa
, prims
, primMask
, primId
, viewportIdx
, rtIdx
);
180 RDTSC_END(FEClipLines
, 1);
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
)
186 SWR_CONTEXT
*pContext
= pDC
->pContext
;
187 RDTSC_BEGIN(FEClipPoints
, pDC
->drawId
);
188 Clipper
<SIMD256
, 1> clipper(workerId
, pDC
);
189 clipper
.ExecuteStage(pa
, prims
, primMask
, primId
, viewportIdx
, rtIdx
);
190 RDTSC_END(FEClipPoints
, 1);
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
)
197 SWR_CONTEXT
*pContext
= pDC
->pContext
;
198 RDTSC_BEGIN(FEClipTriangles
, pDC
->drawId
);
200 enum { VERTS_PER_PRIM
= 3 };
202 Clipper
<SIMD512
, VERTS_PER_PRIM
> clipper(workerId
, pDC
);
204 pa
.useAlternateOffset
= false;
205 clipper
.ExecuteStage(pa
, prims
, primMask
, primId
, viewportIdx
, rtIdx
);
207 RDTSC_END(FEClipTriangles
, 1);
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
)
213 SWR_CONTEXT
*pContext
= pDC
->pContext
;
214 RDTSC_BEGIN(FEClipLines
, pDC
->drawId
);
216 enum { VERTS_PER_PRIM
= 2 };
218 Clipper
<SIMD512
, VERTS_PER_PRIM
> clipper(workerId
, pDC
);
220 pa
.useAlternateOffset
= false;
221 clipper
.ExecuteStage(pa
, prims
, primMask
, primId
, viewportIdx
, rtIdx
);
223 RDTSC_END(FEClipLines
, 1);
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
)
229 SWR_CONTEXT
*pContext
= pDC
->pContext
;
230 RDTSC_BEGIN(FEClipPoints
, pDC
->drawId
);
232 enum { VERTS_PER_PRIM
= 1 };
234 Clipper
<SIMD512
, VERTS_PER_PRIM
> clipper(workerId
, pDC
);
236 pa
.useAlternateOffset
= false;
237 clipper
.ExecuteStage(pa
, prims
, primMask
, primId
, viewportIdx
, rtIdx
);
239 RDTSC_END(FEClipPoints
, 1);