blob: 5ab553402e8c533192618b45fdf005f44d9b8490 [file] [log] [blame]
Nicolas Capens68a82382018-10-02 13:16:55 -04001// 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"
Nicolas Capens68a82382018-10-02 13:16:55 -040019
Nicolas Capens157ba262019-12-10 17:49:14 -050020namespace {
21
22inline void clipEdge(sw::float4 &Vo, const sw::float4 &Vi, const sw::float4 &Vj, float di, float dj)
Nicolas Capens68a82382018-10-02 13:16:55 -040023{
Nicolas Capens157ba262019-12-10 17:49:14 -050024 float D = 1.0f / (dj - di);
Alexis Hetu05953ef2019-05-08 16:56:42 -040025
Nicolas Capens157ba262019-12-10 17:49:14 -050026 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;
Alexis Hetu05953ef2019-05-08 16:56:42 -040030}
Nicolas Capens68a82382018-10-02 13:16:55 -040031
Nicolas Capens157ba262019-12-10 17:49:14 -050032void clipNear(sw::Polygon &polygon)
Alexis Hetu05953ef2019-05-08 16:56:42 -040033{
Nicolas Capens157ba262019-12-10 17:49:14 -050034 const sw::float4 **V = polygon.P[polygon.i];
35 const sw::float4 **T = polygon.P[polygon.i + 1];
Nicolas Capens68a82382018-10-02 13:16:55 -040036
Nicolas Capens157ba262019-12-10 17:49:14 -050037 int t = 0;
38
39 for(int i = 0; i < polygon.n; i++)
Alexis Hetu05953ef2019-05-08 16:56:42 -040040 {
Nicolas Capens157ba262019-12-10 17:49:14 -050041 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)
Alexis Hetu05953ef2019-05-08 16:56:42 -040047 {
Nicolas Capens157ba262019-12-10 17:49:14 -050048 T[t++] = V[i];
Alexis Hetu05953ef2019-05-08 16:56:42 -040049
Nicolas Capens157ba262019-12-10 17:49:14 -050050 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 }
Nicolas Capens68a82382018-10-02 13:16:55 -040064 }
Nicolas Capens157ba262019-12-10 17:49:14 -050065
66 polygon.n = t;
67 polygon.i += 1;
Nicolas Capens68a82382018-10-02 13:16:55 -040068}
Nicolas Capens157ba262019-12-10 17:49:14 -050069
70void 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
108void 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
146void 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
184void 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
222void 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} // anonymous namespace
261
262namespace sw {
263
Sean Risser72b1f012021-04-19 15:02:06 -0400264unsigned int Clipper::ComputeClipFlags(const float4 &v, bool depthClipEnable)
Nicolas Capens157ba262019-12-10 17:49:14 -0500265{
Sean Risser72b1f012021-04-19 15:02:06 -0400266 int depthClipFlags = ((v.z > v.w) ? CLIP_FAR : 0) |
Sean Risser08762e32021-05-05 14:28:24 -0400267 ((v.z < 0) ? CLIP_NEAR : 0);
Ben Claytonfccfc562019-12-17 20:37:31 +0000268 return ((v.x > v.w) ? CLIP_RIGHT : 0) |
269 ((v.y > v.w) ? CLIP_TOP : 0) |
Ben Claytonfccfc562019-12-17 20:37:31 +0000270 ((v.x < -v.w) ? CLIP_LEFT : 0) |
271 ((v.y < -v.w) ? CLIP_BOTTOM : 0) |
Sean Risser72b1f012021-04-19 15:02:06 -0400272 (depthClipEnable ? depthClipFlags : 0) |
Ben Claytonfccfc562019-12-17 20:37:31 +0000273 Clipper::CLIP_FINITE; // FIXME: xyz finite
Nicolas Capens157ba262019-12-10 17:49:14 -0500274}
275
276bool Clipper::Clip(Polygon &polygon, int clipFlagsOr, const DrawCall &draw)
277{
278 if(clipFlagsOr & CLIP_FRUSTUM)
279 {
Ben Claytonfccfc562019-12-17 20:37:31 +0000280 if(clipFlagsOr & CLIP_NEAR) clipNear(polygon);
281 if(polygon.n >= 3)
282 {
283 if(clipFlagsOr & CLIP_FAR) clipFar(polygon);
284 if(polygon.n >= 3)
285 {
286 if(clipFlagsOr & CLIP_LEFT) clipLeft(polygon);
287 if(polygon.n >= 3)
288 {
289 if(clipFlagsOr & CLIP_RIGHT) clipRight(polygon);
290 if(polygon.n >= 3)
291 {
292 if(clipFlagsOr & CLIP_TOP) clipTop(polygon);
293 if(polygon.n >= 3)
294 {
295 if(clipFlagsOr & CLIP_BOTTOM) clipBottom(polygon);
296 }
297 }
298 }
299 }
300 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500301 }
302
303 return polygon.n >= 3;
304}
305
306} // namespace sw