blob: a100f059217d98f2a63e37589c66d2e8a8075ab4 [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"
Nicolas Capens708c24b2017-10-26 13:07:10 -040019#include "Common/Debug.hpp"
John Bauman89401822014-05-06 15:04:28 -040020
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 {
Alexis Hetu6b164c32017-09-20 11:24:52 -040063 int clipFlags = draw.clipFlags;
Nicolas Capens53bf0a12016-05-26 11:19:02 -040064 DrawData &data = *draw.data;
65
John Bauman89401822014-05-06 15:04:28 -040066 if(polygon.n >= 3) {
Alexis Hetu6b164c32017-09-20 11:24:52 -040067 if(clipFlags & CLIP_PLANE0) clipPlane(polygon, data.clipPlane[0]);
John Bauman89401822014-05-06 15:04:28 -040068 if(polygon.n >= 3) {
Alexis Hetu6b164c32017-09-20 11:24:52 -040069 if(clipFlags & CLIP_PLANE1) clipPlane(polygon, data.clipPlane[1]);
John Bauman89401822014-05-06 15:04:28 -040070 if(polygon.n >= 3) {
Alexis Hetu6b164c32017-09-20 11:24:52 -040071 if(clipFlags & CLIP_PLANE2) clipPlane(polygon, data.clipPlane[2]);
John Bauman89401822014-05-06 15:04:28 -040072 if(polygon.n >= 3) {
Alexis Hetu6b164c32017-09-20 11:24:52 -040073 if(clipFlags & CLIP_PLANE3) clipPlane(polygon, data.clipPlane[3]);
John Bauman89401822014-05-06 15:04:28 -040074 if(polygon.n >= 3) {
Alexis Hetu6b164c32017-09-20 11:24:52 -040075 if(clipFlags & CLIP_PLANE4) clipPlane(polygon, data.clipPlane[4]);
John Bauman89401822014-05-06 15:04:28 -040076 if(polygon.n >= 3) {
Alexis Hetu6b164c32017-09-20 11:24:52 -040077 if(clipFlags & CLIP_PLANE5) clipPlane(polygon, data.clipPlane[5]);
John Bauman89401822014-05-06 15:04:28 -040078 }}}}}}
79 }
80
81 return polygon.n >= 3;
82 }
83
84 void Clipper::clipNear(Polygon &polygon)
85 {
John Bauman89401822014-05-06 15:04:28 -040086 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
Nicolas Capens00bfa182016-05-20 21:30:54 -070095 float di = V[i]->z - n * V[i]->w;
96 float dj = V[j]->z - n * V[j]->w;
John Bauman89401822014-05-06 15:04:28 -040097
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);
John Bauman89401822014-05-06 15:04:28 -0400105 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);
John Bauman89401822014-05-06 15:04:28 -0400113 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 {
John Bauman89401822014-05-06 15:04:28 -0400124 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);
John Bauman89401822014-05-06 15:04:28 -0400143 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);
John Bauman89401822014-05-06 15:04:28 -0400151 T[t++] = &polygon.B[polygon.b++];
152 }
153 }
154 }
155
156 polygon.n = t;
157 polygon.i += 1;
158 }
159
Nicolas Capens53bf0a12016-05-26 11:19:02 -0400160 void Clipper::clipLeft(Polygon &polygon)
John Bauman89401822014-05-06 15:04:28 -0400161 {
John Bauman89401822014-05-06 15:04:28 -0400162 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
Nicolas Capens5491cb42015-07-02 15:33:29 -0400171 float di = V[i]->w + V[i]->x;
172 float dj = V[j]->w + V[j]->x;
John Bauman89401822014-05-06 15:04:28 -0400173
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);
John Bauman89401822014-05-06 15:04:28 -0400181 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);
John Bauman89401822014-05-06 15:04:28 -0400189 T[t++] = &polygon.B[polygon.b++];
190 }
191 }
192 }
193
194 polygon.n = t;
195 polygon.i += 1;
196 }
197
Nicolas Capens53bf0a12016-05-26 11:19:02 -0400198 void Clipper::clipRight(Polygon &polygon)
John Bauman89401822014-05-06 15:04:28 -0400199 {
John Bauman89401822014-05-06 15:04:28 -0400200 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
Nicolas Capens5491cb42015-07-02 15:33:29 -0400209 float di = V[i]->w - V[i]->x;
210 float dj = V[j]->w - V[j]->x;
John Bauman89401822014-05-06 15:04:28 -0400211
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);
John Bauman89401822014-05-06 15:04:28 -0400219 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);
John Bauman89401822014-05-06 15:04:28 -0400227 T[t++] = &polygon.B[polygon.b++];
228 }
229 }
230 }
231
232 polygon.n = t;
233 polygon.i += 1;
234 }
235
Nicolas Capens53bf0a12016-05-26 11:19:02 -0400236 void Clipper::clipTop(Polygon &polygon)
John Bauman89401822014-05-06 15:04:28 -0400237 {
John Bauman89401822014-05-06 15:04:28 -0400238 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
Nicolas Capens5491cb42015-07-02 15:33:29 -0400247 float di = V[i]->w - V[i]->y;
248 float dj = V[j]->w - V[j]->y;
John Bauman89401822014-05-06 15:04:28 -0400249
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);
John Bauman89401822014-05-06 15:04:28 -0400257 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);
John Bauman89401822014-05-06 15:04:28 -0400265 T[t++] = &polygon.B[polygon.b++];
266 }
267 }
268 }
269
270 polygon.n = t;
271 polygon.i += 1;
272 }
273
Nicolas Capens53bf0a12016-05-26 11:19:02 -0400274 void Clipper::clipBottom(Polygon &polygon)
John Bauman89401822014-05-06 15:04:28 -0400275 {
John Bauman89401822014-05-06 15:04:28 -0400276 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
Nicolas Capens5491cb42015-07-02 15:33:29 -0400285 float di = V[i]->w + V[i]->y;
286 float dj = V[j]->w + V[j]->y;
John Bauman89401822014-05-06 15:04:28 -0400287
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);
John Bauman89401822014-05-06 15:04:28 -0400295 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);
John Bauman89401822014-05-06 15:04:28 -0400303 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 {
John Bauman89401822014-05-06 15:04:28 -0400314 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}