blob: cfd859ff6dc39abfe4d7d7826ab83c89944735ed [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
John Bauman89401822014-05-06 15:04:28 -04002//
Nicolas Capens0bac2852016-05-07 06:09:58 -04003// 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
John Bauman89401822014-05-06 15:04:28 -04006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// http://www.apache.org/licenses/LICENSE-2.0
John Bauman89401822014-05-06 15:04:28 -04008//
Nicolas Capens0bac2852016-05-07 06:09:58 -04009// 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.
John Bauman89401822014-05-06 15:04:28 -040014
15#include "Clipper.hpp"
16
17#include "Polygon.hpp"
18#include "Renderer.hpp"
19#include "Debug.hpp"
20
John Bauman89401822014-05-06 15:04:28 -040021namespace sw
22{
Nicolas Capens00bfa182016-05-20 21:30:54 -070023 Clipper::Clipper(bool symmetricNormalizedDepth)
John Bauman89401822014-05-06 15:04:28 -040024 {
Nicolas Capens00bfa182016-05-20 21:30:54 -070025 n = symmetricNormalizedDepth ? -1.0f : 0.0f;
John Bauman89401822014-05-06 15:04:28 -040026 }
27
28 Clipper::~Clipper()
29 {
30 }
31
Nicolas Capens53bf0a12016-05-26 11:19:02 -040032 unsigned int Clipper::computeClipFlags(const float4 &v)
33 {
Nicolas Capens00bfa182016-05-20 21:30:54 -070034 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) |
Nicolas Capens53bf0a12016-05-26 11:19:02 -040040 Clipper::CLIP_FINITE; // FIXME: xyz finite
41 }
42
John Bauman89401822014-05-06 15:04:28 -040043 bool Clipper::clip(Polygon &polygon, int clipFlagsOr, const DrawCall &draw)
44 {
Nicolas Capens53bf0a12016-05-26 11:19:02 -040045 if(clipFlagsOr & CLIP_FRUSTUM)
John Bauman89401822014-05-06 15:04:28 -040046 {
47 if(clipFlagsOr & CLIP_NEAR) clipNear(polygon);
48 if(polygon.n >= 3) {
49 if(clipFlagsOr & CLIP_FAR) clipFar(polygon);
50 if(polygon.n >= 3) {
Nicolas Capens53bf0a12016-05-26 11:19:02 -040051 if(clipFlagsOr & CLIP_LEFT) clipLeft(polygon);
John Bauman89401822014-05-06 15:04:28 -040052 if(polygon.n >= 3) {
Nicolas Capens53bf0a12016-05-26 11:19:02 -040053 if(clipFlagsOr & CLIP_RIGHT) clipRight(polygon);
John Bauman89401822014-05-06 15:04:28 -040054 if(polygon.n >= 3) {
Nicolas Capens53bf0a12016-05-26 11:19:02 -040055 if(clipFlagsOr & CLIP_TOP) clipTop(polygon);
John Bauman89401822014-05-06 15:04:28 -040056 if(polygon.n >= 3) {
Nicolas Capens53bf0a12016-05-26 11:19:02 -040057 if(clipFlagsOr & CLIP_BOTTOM) clipBottom(polygon);
John Bauman89401822014-05-06 15:04:28 -040058 }}}}}
59 }
60
Nicolas Capens53bf0a12016-05-26 11:19:02 -040061 if(clipFlagsOr & CLIP_USER)
John Bauman89401822014-05-06 15:04:28 -040062 {
Nicolas Capens53bf0a12016-05-26 11:19:02 -040063 DrawData &data = *draw.data;
64
John Bauman89401822014-05-06 15:04:28 -040065 if(polygon.n >= 3) {
66 if(draw.clipFlags & CLIP_PLANE0) clipPlane(polygon, data.clipPlane[0]);
67 if(polygon.n >= 3) {
68 if(draw.clipFlags & CLIP_PLANE1) clipPlane(polygon, data.clipPlane[1]);
69 if(polygon.n >= 3) {
70 if(draw.clipFlags & CLIP_PLANE2) clipPlane(polygon, data.clipPlane[2]);
71 if(polygon.n >= 3) {
72 if(draw.clipFlags & CLIP_PLANE3) clipPlane(polygon, data.clipPlane[3]);
73 if(polygon.n >= 3) {
74 if(draw.clipFlags & CLIP_PLANE4) clipPlane(polygon, data.clipPlane[4]);
75 if(polygon.n >= 3) {
76 if(draw.clipFlags & CLIP_PLANE5) clipPlane(polygon, data.clipPlane[5]);
77 }}}}}}
78 }
79
80 return polygon.n >= 3;
81 }
82
83 void Clipper::clipNear(Polygon &polygon)
84 {
John Bauman89401822014-05-06 15:04:28 -040085 const float4 **V = polygon.P[polygon.i];
86 const float4 **T = polygon.P[polygon.i + 1];
87
88 int t = 0;
89
90 for(int i = 0; i < polygon.n; i++)
91 {
92 int j = i == polygon.n - 1 ? 0 : i + 1;
93
Nicolas Capens00bfa182016-05-20 21:30:54 -070094 float di = V[i]->z - n * V[i]->w;
95 float dj = V[j]->z - n * V[j]->w;
John Bauman89401822014-05-06 15:04:28 -040096
97 if(di >= 0)
98 {
99 T[t++] = V[i];
100
101 if(dj < 0)
102 {
103 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
John Bauman89401822014-05-06 15:04:28 -0400104 T[t++] = &polygon.B[polygon.b++];
105 }
106 }
107 else
108 {
109 if(dj > 0)
110 {
111 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
John Bauman89401822014-05-06 15:04:28 -0400112 T[t++] = &polygon.B[polygon.b++];
113 }
114 }
115 }
116
117 polygon.n = t;
118 polygon.i += 1;
119 }
120
121 void Clipper::clipFar(Polygon &polygon)
122 {
John Bauman89401822014-05-06 15:04:28 -0400123 const float4 **V = polygon.P[polygon.i];
124 const float4 **T = polygon.P[polygon.i + 1];
125
126 int t = 0;
127
128 for(int i = 0; i < polygon.n; i++)
129 {
130 int j = i == polygon.n - 1 ? 0 : i + 1;
131
132 float di = V[i]->w - V[i]->z;
133 float dj = V[j]->w - V[j]->z;
134
135 if(di >= 0)
136 {
137 T[t++] = V[i];
138
139 if(dj < 0)
140 {
141 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
John Bauman89401822014-05-06 15:04:28 -0400142 T[t++] = &polygon.B[polygon.b++];
143 }
144 }
145 else
146 {
147 if(dj > 0)
148 {
149 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
John Bauman89401822014-05-06 15:04:28 -0400150 T[t++] = &polygon.B[polygon.b++];
151 }
152 }
153 }
154
155 polygon.n = t;
156 polygon.i += 1;
157 }
158
Nicolas Capens53bf0a12016-05-26 11:19:02 -0400159 void Clipper::clipLeft(Polygon &polygon)
John Bauman89401822014-05-06 15:04:28 -0400160 {
John Bauman89401822014-05-06 15:04:28 -0400161 const float4 **V = polygon.P[polygon.i];
162 const float4 **T = polygon.P[polygon.i + 1];
163
164 int t = 0;
165
166 for(int i = 0; i < polygon.n; i++)
167 {
168 int j = i == polygon.n - 1 ? 0 : i + 1;
169
Nicolas Capens5491cb42015-07-02 15:33:29 -0400170 float di = V[i]->w + V[i]->x;
171 float dj = V[j]->w + V[j]->x;
John Bauman89401822014-05-06 15:04:28 -0400172
173 if(di >= 0)
174 {
175 T[t++] = V[i];
176
177 if(dj < 0)
178 {
179 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
John Bauman89401822014-05-06 15:04:28 -0400180 T[t++] = &polygon.B[polygon.b++];
181 }
182 }
183 else
184 {
185 if(dj > 0)
186 {
187 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
John Bauman89401822014-05-06 15:04:28 -0400188 T[t++] = &polygon.B[polygon.b++];
189 }
190 }
191 }
192
193 polygon.n = t;
194 polygon.i += 1;
195 }
196
Nicolas Capens53bf0a12016-05-26 11:19:02 -0400197 void Clipper::clipRight(Polygon &polygon)
John Bauman89401822014-05-06 15:04:28 -0400198 {
John Bauman89401822014-05-06 15:04:28 -0400199 const float4 **V = polygon.P[polygon.i];
200 const float4 **T = polygon.P[polygon.i + 1];
201
202 int t = 0;
203
204 for(int i = 0; i < polygon.n; i++)
205 {
206 int j = i == polygon.n - 1 ? 0 : i + 1;
207
Nicolas Capens5491cb42015-07-02 15:33:29 -0400208 float di = V[i]->w - V[i]->x;
209 float dj = V[j]->w - V[j]->x;
John Bauman89401822014-05-06 15:04:28 -0400210
211 if(di >= 0)
212 {
213 T[t++] = V[i];
214
215 if(dj < 0)
216 {
217 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
John Bauman89401822014-05-06 15:04:28 -0400218 T[t++] = &polygon.B[polygon.b++];
219 }
220 }
221 else
222 {
223 if(dj > 0)
224 {
225 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
John Bauman89401822014-05-06 15:04:28 -0400226 T[t++] = &polygon.B[polygon.b++];
227 }
228 }
229 }
230
231 polygon.n = t;
232 polygon.i += 1;
233 }
234
Nicolas Capens53bf0a12016-05-26 11:19:02 -0400235 void Clipper::clipTop(Polygon &polygon)
John Bauman89401822014-05-06 15:04:28 -0400236 {
John Bauman89401822014-05-06 15:04:28 -0400237 const float4 **V = polygon.P[polygon.i];
238 const float4 **T = polygon.P[polygon.i + 1];
239
240 int t = 0;
241
242 for(int i = 0; i < polygon.n; i++)
243 {
244 int j = i == polygon.n - 1 ? 0 : i + 1;
245
Nicolas Capens5491cb42015-07-02 15:33:29 -0400246 float di = V[i]->w - V[i]->y;
247 float dj = V[j]->w - V[j]->y;
John Bauman89401822014-05-06 15:04:28 -0400248
249 if(di >= 0)
250 {
251 T[t++] = V[i];
252
253 if(dj < 0)
254 {
255 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
John Bauman89401822014-05-06 15:04:28 -0400256 T[t++] = &polygon.B[polygon.b++];
257 }
258 }
259 else
260 {
261 if(dj > 0)
262 {
263 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
John Bauman89401822014-05-06 15:04:28 -0400264 T[t++] = &polygon.B[polygon.b++];
265 }
266 }
267 }
268
269 polygon.n = t;
270 polygon.i += 1;
271 }
272
Nicolas Capens53bf0a12016-05-26 11:19:02 -0400273 void Clipper::clipBottom(Polygon &polygon)
John Bauman89401822014-05-06 15:04:28 -0400274 {
John Bauman89401822014-05-06 15:04:28 -0400275 const float4 **V = polygon.P[polygon.i];
276 const float4 **T = polygon.P[polygon.i + 1];
277
278 int t = 0;
279
280 for(int i = 0; i < polygon.n; i++)
281 {
282 int j = i == polygon.n - 1 ? 0 : i + 1;
283
Nicolas Capens5491cb42015-07-02 15:33:29 -0400284 float di = V[i]->w + V[i]->y;
285 float dj = V[j]->w + V[j]->y;
John Bauman89401822014-05-06 15:04:28 -0400286
287 if(di >= 0)
288 {
289 T[t++] = V[i];
290
291 if(dj < 0)
292 {
293 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
John Bauman89401822014-05-06 15:04:28 -0400294 T[t++] = &polygon.B[polygon.b++];
295 }
296 }
297 else
298 {
299 if(dj > 0)
300 {
301 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
John Bauman89401822014-05-06 15:04:28 -0400302 T[t++] = &polygon.B[polygon.b++];
303 }
304 }
305 }
306
307 polygon.n = t;
308 polygon.i += 1;
309 }
310
311 void Clipper::clipPlane(Polygon &polygon, const Plane &p)
312 {
John Bauman89401822014-05-06 15:04:28 -0400313 const float4 **V = polygon.P[polygon.i];
314 const float4 **T = polygon.P[polygon.i + 1];
315
316 int t = 0;
317
318 for(int i = 0; i < polygon.n; i++)
319 {
320 int j = i == polygon.n - 1 ? 0 : i + 1;
321
322 float di = p.A * V[i]->x + p.B * V[i]->y + p.C * V[i]->z + p.D * V[i]->w;
323 float dj = p.A * V[j]->x + p.B * V[j]->y + p.C * V[j]->z + p.D * V[j]->w;
324
325 if(di >= 0)
326 {
327 T[t++] = V[i];
328
329 if(dj < 0)
330 {
331 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
332 T[t++] = &polygon.B[polygon.b++];
333 }
334 }
335 else
336 {
337 if(dj > 0)
338 {
339 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
340 T[t++] = &polygon.B[polygon.b++];
341 }
342 }
343 }
344
345 polygon.n = t;
346 polygon.i += 1;
347 }
348
349 inline void Clipper::clipEdge(float4 &Vo, const float4 &Vi, const float4 &Vj, float di, float dj) const
350 {
351 float D = 1.0f / (dj - di);
352
353 Vo.x = (dj * Vi.x - di * Vj.x) * D;
354 Vo.y = (dj * Vi.y - di * Vj.y) * D;
355 Vo.z = (dj * Vi.z - di * Vj.z) * D;
356 Vo.w = (dj * Vi.w - di * Vj.w) * D;
357 }
358}