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
20namespace
21{
22 inline void clipEdge(sw::float4 &Vo, const sw::float4 &Vi, const sw::float4 &Vj, float di, float dj)
23 {
24 float D = 1.0f / (dj - di);
25
26 Vo.x = (dj * Vi.x - di * Vj.x) * D;
27 Vo.y = (dj * Vi.y - di * Vj.y) * D;
28 Vo.z = (dj * Vi.z - di * Vj.z) * D;
29 Vo.w = (dj * Vi.w - di * Vj.w) * D;
30 }
31
32 void clipNear(sw::Polygon &polygon)
33 {
34 const sw::float4 **V = polygon.P[polygon.i];
35 const sw::float4 **T = polygon.P[polygon.i + 1];
36
37 int t = 0;
38
39 for(int i = 0; i < polygon.n; i++)
40 {
41 int j = i == polygon.n - 1 ? 0 : i + 1;
42
43 float di = V[i]->z;
44 float dj = V[j]->z;
45
46 if(di >= 0)
47 {
48 T[t++] = V[i];
49
50 if(dj < 0)
51 {
52 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
53 T[t++] = &polygon.B[polygon.b++];
54 }
55 }
56 else
57 {
58 if(dj > 0)
59 {
60 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
61 T[t++] = &polygon.B[polygon.b++];
62 }
63 }
64 }
65
66 polygon.n = t;
67 polygon.i += 1;
68 }
69
70 void clipFar(sw::Polygon &polygon)
71 {
72 const sw::float4 **V = polygon.P[polygon.i];
73 const sw::float4 **T = polygon.P[polygon.i + 1];
74
75 int t = 0;
76
77 for(int i = 0; i < polygon.n; i++)
78 {
79 int j = i == polygon.n - 1 ? 0 : i + 1;
80
81 float di = V[i]->w - V[i]->z;
82 float dj = V[j]->w - V[j]->z;
83
84 if(di >= 0)
85 {
86 T[t++] = V[i];
87
88 if(dj < 0)
89 {
90 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
91 T[t++] = &polygon.B[polygon.b++];
92 }
93 }
94 else
95 {
96 if(dj > 0)
97 {
98 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
99 T[t++] = &polygon.B[polygon.b++];
100 }
101 }
102 }
103
104 polygon.n = t;
105 polygon.i += 1;
106 }
107
108 void clipLeft(sw::Polygon &polygon)
109 {
110 const sw::float4 **V = polygon.P[polygon.i];
111 const sw::float4 **T = polygon.P[polygon.i + 1];
112
113 int t = 0;
114
115 for(int i = 0; i < polygon.n; i++)
116 {
117 int j = i == polygon.n - 1 ? 0 : i + 1;
118
119 float di = V[i]->w + V[i]->x;
120 float dj = V[j]->w + V[j]->x;
121
122 if(di >= 0)
123 {
124 T[t++] = V[i];
125
126 if(dj < 0)
127 {
128 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
129 T[t++] = &polygon.B[polygon.b++];
130 }
131 }
132 else
133 {
134 if(dj > 0)
135 {
136 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
137 T[t++] = &polygon.B[polygon.b++];
138 }
139 }
140 }
141
142 polygon.n = t;
143 polygon.i += 1;
144 }
145
146 void clipRight(sw::Polygon &polygon)
147 {
148 const sw::float4 **V = polygon.P[polygon.i];
149 const sw::float4 **T = polygon.P[polygon.i + 1];
150
151 int t = 0;
152
153 for(int i = 0; i < polygon.n; i++)
154 {
155 int j = i == polygon.n - 1 ? 0 : i + 1;
156
157 float di = V[i]->w - V[i]->x;
158 float dj = V[j]->w - V[j]->x;
159
160 if(di >= 0)
161 {
162 T[t++] = V[i];
163
164 if(dj < 0)
165 {
166 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
167 T[t++] = &polygon.B[polygon.b++];
168 }
169 }
170 else
171 {
172 if(dj > 0)
173 {
174 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
175 T[t++] = &polygon.B[polygon.b++];
176 }
177 }
178 }
179
180 polygon.n = t;
181 polygon.i += 1;
182 }
183
184 void clipTop(sw::Polygon &polygon)
185 {
186 const sw::float4 **V = polygon.P[polygon.i];
187 const sw::float4 **T = polygon.P[polygon.i + 1];
188
189 int t = 0;
190
191 for(int i = 0; i < polygon.n; i++)
192 {
193 int j = i == polygon.n - 1 ? 0 : i + 1;
194
195 float di = V[i]->w - V[i]->y;
196 float dj = V[j]->w - V[j]->y;
197
198 if(di >= 0)
199 {
200 T[t++] = V[i];
201
202 if(dj < 0)
203 {
204 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
205 T[t++] = &polygon.B[polygon.b++];
206 }
207 }
208 else
209 {
210 if(dj > 0)
211 {
212 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
213 T[t++] = &polygon.B[polygon.b++];
214 }
215 }
216 }
217
218 polygon.n = t;
219 polygon.i += 1;
220 }
221
222 void clipBottom(sw::Polygon &polygon)
223 {
224 const sw::float4 **V = polygon.P[polygon.i];
225 const sw::float4 **T = polygon.P[polygon.i + 1];
226
227 int t = 0;
228
229 for(int i = 0; i < polygon.n; i++)
230 {
231 int j = i == polygon.n - 1 ? 0 : i + 1;
232
233 float di = V[i]->w + V[i]->y;
234 float dj = V[j]->w + V[j]->y;
235
236 if(di >= 0)
237 {
238 T[t++] = V[i];
239
240 if(dj < 0)
241 {
242 clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
243 T[t++] = &polygon.B[polygon.b++];
244 }
245 }
246 else
247 {
248 if(dj > 0)
249 {
250 clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
251 T[t++] = &polygon.B[polygon.b++];
252 }
253 }
254 }
255
256 polygon.n = t;
257 polygon.i += 1;
258 }
259}
260
261namespace sw
262{
263 unsigned int Clipper::ComputeClipFlags(const float4 &v)
264 {
265 return ((v.x > v.w) ? CLIP_RIGHT : 0) |
266 ((v.y > v.w) ? CLIP_TOP : 0) |
267 ((v.z > v.w) ? CLIP_FAR : 0) |
268 ((v.x < -v.w) ? CLIP_LEFT : 0) |
269 ((v.y < -v.w) ? CLIP_BOTTOM : 0) |
270 ((v.z < 0) ? CLIP_NEAR : 0) |
271 Clipper::CLIP_FINITE; // FIXME: xyz finite
272 }
273
274 bool Clipper::Clip(Polygon &polygon, int clipFlagsOr, const DrawCall &draw)
275 {
276 if(clipFlagsOr & CLIP_FRUSTUM)
277 {
278 if(clipFlagsOr & CLIP_NEAR) clipNear(polygon);
279 if(polygon.n >= 3) {
280 if(clipFlagsOr & CLIP_FAR) clipFar(polygon);
281 if(polygon.n >= 3) {
282 if(clipFlagsOr & CLIP_LEFT) clipLeft(polygon);
283 if(polygon.n >= 3) {
284 if(clipFlagsOr & CLIP_RIGHT) clipRight(polygon);
285 if(polygon.n >= 3) {
286 if(clipFlagsOr & CLIP_TOP) clipTop(polygon);
287 if(polygon.n >= 3) {
288 if(clipFlagsOr & CLIP_BOTTOM) clipBottom(polygon);
289 }}}}}
290 }
291
292 return polygon.n >= 3;
293 }
294}
295