1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "Clipper.hpp"
16
17#include "Polygon.hpp"
18#include "Renderer.hpp"
19#include "Common/Debug.hpp"
20
21namespace sw
22{
23 Clipper::Clipper(bool symmetricNormalizedDepth)
24 {
25 n = symmetricNormalizedDepth ? -1.0f : 0.0f;
26 }
27
28 Clipper::~Clipper()
29 {
30 }
31
32 unsigned int Clipper::computeClipFlags(const float4 &v)
33 {
34 return ((v.x > v.w) ? CLIP_RIGHT : 0) |
35 ((v.y > v.w) ? CLIP_TOP : 0) |
36 ((v.z > v.w) ? CLIP_FAR : 0) |
37 ((v.x < -v.w) ? CLIP_LEFT : 0) |
38 ((v.y < -v.w) ? CLIP_BOTTOM : 0) |
39 ((v.z < n * v.w) ? CLIP_NEAR : 0) |
40 Clipper::CLIP_FINITE; // FIXME: xyz finite
41 }
42
43 bool Clipper::clip(Polygon &polygon, int clipFlagsOr, const DrawCall &draw)
44 {
45 if(clipFlagsOr & CLIP_FRUSTUM)
46 {
47 if(clipFlagsOr & CLIP_NEAR) clipNear(polygon);
48 if(polygon.n >= 3) {
49 if(clipFlagsOr & CLIP_FAR) clipFar(polygon);
50 if(polygon.n >= 3) {
51 if(clipFlagsOr & CLIP_LEFT) clipLeft(polygon);
52 if(polygon.n >= 3) {
53 if(clipFlagsOr & CLIP_RIGHT) clipRight(polygon);
54 if(polygon.n >= 3) {
55 if(clipFlagsOr & CLIP_TOP) clipTop(polygon);
56 if(polygon.n >= 3) {
57 if(clipFlagsOr & CLIP_BOTTOM) clipBottom(polygon);
58 }}}}}
59 }
60
61 if(clipFlagsOr & CLIP_USER)
62 {
63 int clipFlags = draw.clipFlags;
64 DrawData &data = *draw.data;
65
66 if(polygon.n >= 3) {
67 if(clipFlags & CLIP_PLANE0) clipPlane(polygon, data.clipPlane[0]);
68 if(polygon.n >= 3) {
69 if(clipFlags & CLIP_PLANE1) clipPlane(polygon, data.clipPlane[1]);
70 if(polygon.n >= 3) {
71 if(clipFlags & CLIP_PLANE2) clipPlane(polygon, data.clipPlane[2]);
72 if(polygon.n >= 3) {
73 if(clipFlags & CLIP_PLANE3) clipPlane(polygon, data.clipPlane[3]);
74 if(polygon.n >= 3) {
75 if(clipFlags & CLIP_PLANE4) clipPlane(polygon, data.clipPlane[4]);
76 if(polygon.n >= 3) {
77 if(clipFlags & CLIP_PLANE5) clipPlane(polygon, data.clipPlane[5]);
78 }}}}}}
79 }
80
81 return polygon.n >= 3;
82 }
83
84 void Clipper::clipNear(Polygon &polygon)
85 {
86 const float4 **V = polygon.P[polygon.i];
87 const float4 **T = polygon.P[polygon.i + 1];
88
89 int t = 0;
90
91 for(int i = 0; i < polygon.n; i++)
92 {
93 int j = i == polygon.n - 1 ? 0 : i + 1;
94
95 float di = V[i]->z - n * V[i]->w;
96 float dj = V[j]->z - n * V[j]->w;
97
98 if(di >= 0)
99 {
100 T[t++] = V[i];
101
102 if(dj < 0)
103 {
104 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
105 T[t++] = &polygon.B[polygon.b++];
106 }
107 }
108 else
109 {
110 if(dj > 0)
111 {
112 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
113 T[t++] = &polygon.B[polygon.b++];
114 }
115 }
116 }
117
118 polygon.n = t;
119 polygon.i += 1;
120 }
121
122 void Clipper::clipFar(Polygon &polygon)
123 {
124 const float4 **V = polygon.P[polygon.i];
125 const float4 **T = polygon.P[polygon.i + 1];
126
127 int t = 0;
128
129 for(int i = 0; i < polygon.n; i++)
130 {
131 int j = i == polygon.n - 1 ? 0 : i + 1;
132
133 float di = V[i]->w - V[i]->z;
134 float dj = V[j]->w - V[j]->z;
135
136 if(di >= 0)
137 {
138 T[t++] = V[i];
139
140 if(dj < 0)
141 {
142 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
143 T[t++] = &polygon.B[polygon.b++];
144 }
145 }
146 else
147 {
148 if(dj > 0)
149 {
150 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
151 T[t++] = &polygon.B[polygon.b++];
152 }
153 }
154 }
155
156 polygon.n = t;
157 polygon.i += 1;
158 }
159
160 void Clipper::clipLeft(Polygon &polygon)
161 {
162 const float4 **V = polygon.P[polygon.i];
163 const float4 **T = polygon.P[polygon.i + 1];
164
165 int t = 0;
166
167 for(int i = 0; i < polygon.n; i++)
168 {
169 int j = i == polygon.n - 1 ? 0 : i + 1;
170
171 float di = V[i]->w + V[i]->x;
172 float dj = V[j]->w + V[j]->x;
173
174 if(di >= 0)
175 {
176 T[t++] = V[i];
177
178 if(dj < 0)
179 {
180 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
181 T[t++] = &polygon.B[polygon.b++];
182 }
183 }
184 else
185 {
186 if(dj > 0)
187 {
188 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
189 T[t++] = &polygon.B[polygon.b++];
190 }
191 }
192 }
193
194 polygon.n = t;
195 polygon.i += 1;
196 }
197
198 void Clipper::clipRight(Polygon &polygon)
199 {
200 const float4 **V = polygon.P[polygon.i];
201 const float4 **T = polygon.P[polygon.i + 1];
202
203 int t = 0;
204
205 for(int i = 0; i < polygon.n; i++)
206 {
207 int j = i == polygon.n - 1 ? 0 : i + 1;
208
209 float di = V[i]->w - V[i]->x;
210 float dj = V[j]->w - V[j]->x;
211
212 if(di >= 0)
213 {
214 T[t++] = V[i];
215
216 if(dj < 0)
217 {
218 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
219 T[t++] = &polygon.B[polygon.b++];
220 }
221 }
222 else
223 {
224 if(dj > 0)
225 {
226 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
227 T[t++] = &polygon.B[polygon.b++];
228 }
229 }
230 }
231
232 polygon.n = t;
233 polygon.i += 1;
234 }
235
236 void Clipper::clipTop(Polygon &polygon)
237 {
238 const float4 **V = polygon.P[polygon.i];
239 const float4 **T = polygon.P[polygon.i + 1];
240
241 int t = 0;
242
243 for(int i = 0; i < polygon.n; i++)
244 {
245 int j = i == polygon.n - 1 ? 0 : i + 1;
246
247 float di = V[i]->w - V[i]->y;
248 float dj = V[j]->w - V[j]->y;
249
250 if(di >= 0)
251 {
252 T[t++] = V[i];
253
254 if(dj < 0)
255 {
256 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
257 T[t++] = &polygon.B[polygon.b++];
258 }
259 }
260 else
261 {
262 if(dj > 0)
263 {
264 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
265 T[t++] = &polygon.B[polygon.b++];
266 }
267 }
268 }
269
270 polygon.n = t;
271 polygon.i += 1;
272 }
273
274 void Clipper::clipBottom(Polygon &polygon)
275 {
276 const float4 **V = polygon.P[polygon.i];
277 const float4 **T = polygon.P[polygon.i + 1];
278
279 int t = 0;
280
281 for(int i = 0; i < polygon.n; i++)
282 {
283 int j = i == polygon.n - 1 ? 0 : i + 1;
284
285 float di = V[i]->w + V[i]->y;
286 float dj = V[j]->w + V[j]->y;
287
288 if(di >= 0)
289 {
290 T[t++] = V[i];
291
292 if(dj < 0)
293 {
294 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
295 T[t++] = &polygon.B[polygon.b++];
296 }
297 }
298 else
299 {
300 if(dj > 0)
301 {
302 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
303 T[t++] = &polygon.B[polygon.b++];
304 }
305 }
306 }
307
308 polygon.n = t;
309 polygon.i += 1;
310 }
311
312 void Clipper::clipPlane(Polygon &polygon, const Plane &p)
313 {
314 const float4 **V = polygon.P[polygon.i];
315 const float4 **T = polygon.P[polygon.i + 1];
316
317 int t = 0;
318
319 for(int i = 0; i < polygon.n; i++)
320 {
321 int j = i == polygon.n - 1 ? 0 : i + 1;
322
323 float di = p.A * V[i]->x + p.B * V[i]->y + p.C * V[i]->z + p.D * V[i]->w;
324 float dj = p.A * V[j]->x + p.B * V[j]->y + p.C * V[j]->z + p.D * V[j]->w;
325
326 if(di >= 0)
327 {
328 T[t++] = V[i];
329
330 if(dj < 0)
331 {
332 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
333 T[t++] = &polygon.B[polygon.b++];
334 }
335 }
336 else
337 {
338 if(dj > 0)
339 {
340 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
341 T[t++] = &polygon.B[polygon.b++];
342 }
343 }
344 }
345
346 polygon.n = t;
347 polygon.i += 1;
348 }
349
350 inline void Clipper::clipEdge(float4 &Vo, const float4 &Vi, const float4 &Vj, float di, float dj) const
351 {
352 float D = 1.0f / (dj - di);
353
354 Vo.x = (dj * Vi.x - di * Vj.x) * D;
355 Vo.y = (dj * Vi.y - di * Vj.y) * D;
356 Vo.z = (dj * Vi.z - di * Vj.z) * D;
357 Vo.w = (dj * Vi.w - di * Vj.w) * D;
358 }
359}
360