OSDN Git Service

Fix resetting current display when no current context.
[android-x86/external-swiftshader.git] / src / Renderer / Clipper.cpp
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 #include "Debug.hpp"
20
21 namespace sw
22 {
23         Clipper::Clipper(bool symmetricNormalizedDepth)
24         {
25                 n = symmetricNormalizedDepth ? -1.0f : 0.0f;
26         }
27
28         Clipper::~Clipper()
29         {
30         }
31
32         unsigned int Clipper::computeClipFlags(const float4 &v)
33         {
34                 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) |
40                        Clipper::CLIP_FINITE;   // FIXME: xyz finite
41         }
42
43         bool Clipper::clip(Polygon &polygon, int clipFlagsOr, const DrawCall &draw)
44         {
45                 if(clipFlagsOr & CLIP_FRUSTUM)
46                 {
47                         if(clipFlagsOr & CLIP_NEAR)   clipNear(polygon);
48                         if(polygon.n >= 3) {
49                         if(clipFlagsOr & CLIP_FAR)    clipFar(polygon);
50                         if(polygon.n >= 3) {
51                         if(clipFlagsOr & CLIP_LEFT)   clipLeft(polygon);
52                         if(polygon.n >= 3) {
53                         if(clipFlagsOr & CLIP_RIGHT)  clipRight(polygon);
54                         if(polygon.n >= 3) {
55                         if(clipFlagsOr & CLIP_TOP)    clipTop(polygon);
56                         if(polygon.n >= 3) {
57                         if(clipFlagsOr & CLIP_BOTTOM) clipBottom(polygon);
58                         }}}}}
59                 }
60
61                 if(clipFlagsOr & CLIP_USER)
62                 {
63                         DrawData &data = *draw.data;
64
65                         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         {
85                 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
94                         float di = V[i]->z - n * V[i]->w;
95                         float dj = V[j]->z - n * V[j]->w;
96
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);
104                                         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);
112                                         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         {
123                 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);
142                                         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);
150                                         T[t++] = &polygon.B[polygon.b++];
151                                 }
152                         }
153                 }
154
155                 polygon.n = t;
156                 polygon.i += 1;
157         }
158
159         void Clipper::clipLeft(Polygon &polygon)
160         {
161                 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
170                         float di = V[i]->w + V[i]->x;
171                         float dj = V[j]->w + V[j]->x;
172
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);
180                                         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);
188                                         T[t++] = &polygon.B[polygon.b++];
189                                 }
190                         }
191                 }
192
193                 polygon.n = t;
194                 polygon.i += 1;
195         }
196
197         void Clipper::clipRight(Polygon &polygon)
198         {
199                 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
208                         float di = V[i]->w - V[i]->x;
209                         float dj = V[j]->w - V[j]->x;
210
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);
218                                         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);
226                                         T[t++] = &polygon.B[polygon.b++];
227                                 }
228                         }
229                 }
230
231                 polygon.n = t;
232                 polygon.i += 1;
233         }
234
235         void Clipper::clipTop(Polygon &polygon)
236         {
237                 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
246                         float di = V[i]->w - V[i]->y;
247                         float dj = V[j]->w - V[j]->y;
248
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);
256                                         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);
264                                         T[t++] = &polygon.B[polygon.b++];
265                                 }
266                         }
267                 }
268
269                 polygon.n = t;
270                 polygon.i += 1;
271         }
272
273         void Clipper::clipBottom(Polygon &polygon)
274         {
275                 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
284                         float di = V[i]->w + V[i]->y;
285                         float dj = V[j]->w + V[j]->y;
286
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);
294                                         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);
302                                         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         {
313                 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 }