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