swr/rast: Move clip/cull enables in API
[mesa.git] / src / gallium / drivers / swr / rasterizer / core / clip.cpp
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
40 float ComputeInterpFactor(float boundaryCoord0, float boundaryCoord1)
41 {
42 return (boundaryCoord0 / (boundaryCoord0 - boundaryCoord1));
43 }
44
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.
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>
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>
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
163 void ClipTriangles(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[], uint32_t primMask, simdscalari const &primId)
164 {
165 SWR_CONTEXT *pContext = pDC->pContext;
166 AR_BEGIN(FEClipTriangles, pDC->drawId);
167 Clipper<SIMD256, 3> clipper(workerId, pDC);
168 clipper.ExecuteStage(pa, prims, primMask, primId);
169 AR_END(FEClipTriangles, 1);
170 }
171
172 void ClipLines(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[], uint32_t primMask, simdscalari const &primId)
173 {
174 SWR_CONTEXT *pContext = pDC->pContext;
175 AR_BEGIN(FEClipLines, pDC->drawId);
176 Clipper<SIMD256, 2> clipper(workerId, pDC);
177 clipper.ExecuteStage(pa, prims, primMask, primId);
178 AR_END(FEClipLines, 1);
179 }
180
181 void ClipPoints(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[], uint32_t primMask, simdscalari const &primId)
182 {
183 SWR_CONTEXT *pContext = pDC->pContext;
184 AR_BEGIN(FEClipPoints, pDC->drawId);
185 Clipper<SIMD256, 1> clipper(workerId, pDC);
186 clipper.ExecuteStage(pa, prims, primMask, primId);
187 AR_END(FEClipPoints, 1);
188 }
189
190 #if USE_SIMD16_FRONTEND
191 void SIMDCALL ClipTriangles_simd16(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simd16vector prims[], uint32_t primMask, simd16scalari const &primId)
192 {
193 SWR_CONTEXT *pContext = pDC->pContext;
194 AR_BEGIN(FEClipTriangles, pDC->drawId);
195
196 enum { VERTS_PER_PRIM = 3 };
197
198 Clipper<SIMD512, VERTS_PER_PRIM> clipper(workerId, pDC);
199
200 pa.useAlternateOffset = false;
201 clipper.ExecuteStage(pa, prims, primMask, primId);
202
203 AR_END(FEClipTriangles, 1);
204 }
205
206 void SIMDCALL ClipLines_simd16(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simd16vector prims[], uint32_t primMask, simd16scalari const &primId)
207 {
208 SWR_CONTEXT *pContext = pDC->pContext;
209 AR_BEGIN(FEClipLines, pDC->drawId);
210
211 enum { VERTS_PER_PRIM = 2 };
212
213 Clipper<SIMD512, VERTS_PER_PRIM> clipper(workerId, pDC);
214
215 pa.useAlternateOffset = false;
216 clipper.ExecuteStage(pa, prims, primMask, primId);
217
218 AR_END(FEClipLines, 1);
219 }
220
221 void SIMDCALL ClipPoints_simd16(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simd16vector prims[], uint32_t primMask, simd16scalari const &primId)
222 {
223 SWR_CONTEXT *pContext = pDC->pContext;
224 AR_BEGIN(FEClipPoints, pDC->drawId);
225
226 enum { VERTS_PER_PRIM = 1 };
227
228 Clipper<SIMD512, VERTS_PER_PRIM> clipper(workerId, pDC);
229
230 pa.useAlternateOffset = false;
231 clipper.ExecuteStage(pa, prims, primMask, primId);
232
233 AR_END(FEClipPoints, 1);
234 }
235
236 #endif
237