|  | // Copyright 2016 The SwiftShader Authors. All Rights Reserved. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //    http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | #include "Clipper.hpp" | 
|  |  | 
|  | #include "Polygon.hpp" | 
|  | #include "Renderer.hpp" | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | inline void clipEdge(sw::float4 &Vo, const sw::float4 &Vi, const sw::float4 &Vj, float di, float dj) | 
|  | { | 
|  | float D = 1.0f / (dj - di); | 
|  |  | 
|  | Vo.x = (dj * Vi.x - di * Vj.x) * D; | 
|  | Vo.y = (dj * Vi.y - di * Vj.y) * D; | 
|  | Vo.z = (dj * Vi.z - di * Vj.z) * D; | 
|  | Vo.w = (dj * Vi.w - di * Vj.w) * D; | 
|  | } | 
|  |  | 
|  | void clipNear(sw::Polygon &polygon) | 
|  | { | 
|  | const sw::float4 **V = polygon.P[polygon.i]; | 
|  | const sw::float4 **T = polygon.P[polygon.i + 1]; | 
|  |  | 
|  | int t = 0; | 
|  |  | 
|  | for(int i = 0; i < polygon.n; i++) | 
|  | { | 
|  | int j = i == polygon.n - 1 ? 0 : i + 1; | 
|  |  | 
|  | float di = V[i]->z; | 
|  | float dj = V[j]->z; | 
|  |  | 
|  | if(di >= 0) | 
|  | { | 
|  | T[t++] = V[i]; | 
|  |  | 
|  | if(dj < 0) | 
|  | { | 
|  | clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj); | 
|  | T[t++] = &polygon.B[polygon.b++]; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | if(dj > 0) | 
|  | { | 
|  | clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di); | 
|  | T[t++] = &polygon.B[polygon.b++]; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | polygon.n = t; | 
|  | polygon.i += 1; | 
|  | } | 
|  |  | 
|  | void clipFar(sw::Polygon &polygon) | 
|  | { | 
|  | const sw::float4 **V = polygon.P[polygon.i]; | 
|  | const sw::float4 **T = polygon.P[polygon.i + 1]; | 
|  |  | 
|  | int t = 0; | 
|  |  | 
|  | for(int i = 0; i < polygon.n; i++) | 
|  | { | 
|  | int j = i == polygon.n - 1 ? 0 : i + 1; | 
|  |  | 
|  | float di = V[i]->w - V[i]->z; | 
|  | float dj = V[j]->w - V[j]->z; | 
|  |  | 
|  | if(di >= 0) | 
|  | { | 
|  | T[t++] = V[i]; | 
|  |  | 
|  | if(dj < 0) | 
|  | { | 
|  | clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj); | 
|  | T[t++] = &polygon.B[polygon.b++]; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | if(dj > 0) | 
|  | { | 
|  | clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di); | 
|  | T[t++] = &polygon.B[polygon.b++]; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | polygon.n = t; | 
|  | polygon.i += 1; | 
|  | } | 
|  |  | 
|  | void clipLeft(sw::Polygon &polygon) | 
|  | { | 
|  | const sw::float4 **V = polygon.P[polygon.i]; | 
|  | const sw::float4 **T = polygon.P[polygon.i + 1]; | 
|  |  | 
|  | int t = 0; | 
|  |  | 
|  | for(int i = 0; i < polygon.n; i++) | 
|  | { | 
|  | int j = i == polygon.n - 1 ? 0 : i + 1; | 
|  |  | 
|  | float di = V[i]->w + V[i]->x; | 
|  | float dj = V[j]->w + V[j]->x; | 
|  |  | 
|  | if(di >= 0) | 
|  | { | 
|  | T[t++] = V[i]; | 
|  |  | 
|  | if(dj < 0) | 
|  | { | 
|  | clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj); | 
|  | T[t++] = &polygon.B[polygon.b++]; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | if(dj > 0) | 
|  | { | 
|  | clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di); | 
|  | T[t++] = &polygon.B[polygon.b++]; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | polygon.n = t; | 
|  | polygon.i += 1; | 
|  | } | 
|  |  | 
|  | void clipRight(sw::Polygon &polygon) | 
|  | { | 
|  | const sw::float4 **V = polygon.P[polygon.i]; | 
|  | const sw::float4 **T = polygon.P[polygon.i + 1]; | 
|  |  | 
|  | int t = 0; | 
|  |  | 
|  | for(int i = 0; i < polygon.n; i++) | 
|  | { | 
|  | int j = i == polygon.n - 1 ? 0 : i + 1; | 
|  |  | 
|  | float di = V[i]->w - V[i]->x; | 
|  | float dj = V[j]->w - V[j]->x; | 
|  |  | 
|  | if(di >= 0) | 
|  | { | 
|  | T[t++] = V[i]; | 
|  |  | 
|  | if(dj < 0) | 
|  | { | 
|  | clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj); | 
|  | T[t++] = &polygon.B[polygon.b++]; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | if(dj > 0) | 
|  | { | 
|  | clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di); | 
|  | T[t++] = &polygon.B[polygon.b++]; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | polygon.n = t; | 
|  | polygon.i += 1; | 
|  | } | 
|  |  | 
|  | void clipTop(sw::Polygon &polygon) | 
|  | { | 
|  | const sw::float4 **V = polygon.P[polygon.i]; | 
|  | const sw::float4 **T = polygon.P[polygon.i + 1]; | 
|  |  | 
|  | int t = 0; | 
|  |  | 
|  | for(int i = 0; i < polygon.n; i++) | 
|  | { | 
|  | int j = i == polygon.n - 1 ? 0 : i + 1; | 
|  |  | 
|  | float di = V[i]->w - V[i]->y; | 
|  | float dj = V[j]->w - V[j]->y; | 
|  |  | 
|  | if(di >= 0) | 
|  | { | 
|  | T[t++] = V[i]; | 
|  |  | 
|  | if(dj < 0) | 
|  | { | 
|  | clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj); | 
|  | T[t++] = &polygon.B[polygon.b++]; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | if(dj > 0) | 
|  | { | 
|  | clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di); | 
|  | T[t++] = &polygon.B[polygon.b++]; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | polygon.n = t; | 
|  | polygon.i += 1; | 
|  | } | 
|  |  | 
|  | void clipBottom(sw::Polygon &polygon) | 
|  | { | 
|  | const sw::float4 **V = polygon.P[polygon.i]; | 
|  | const sw::float4 **T = polygon.P[polygon.i + 1]; | 
|  |  | 
|  | int t = 0; | 
|  |  | 
|  | for(int i = 0; i < polygon.n; i++) | 
|  | { | 
|  | int j = i == polygon.n - 1 ? 0 : i + 1; | 
|  |  | 
|  | float di = V[i]->w + V[i]->y; | 
|  | float dj = V[j]->w + V[j]->y; | 
|  |  | 
|  | if(di >= 0) | 
|  | { | 
|  | T[t++] = V[i]; | 
|  |  | 
|  | if(dj < 0) | 
|  | { | 
|  | clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj); | 
|  | T[t++] = &polygon.B[polygon.b++]; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | if(dj > 0) | 
|  | { | 
|  | clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di); | 
|  | T[t++] = &polygon.B[polygon.b++]; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | polygon.n = t; | 
|  | polygon.i += 1; | 
|  | } | 
|  |  | 
|  | }  // anonymous namespace | 
|  |  | 
|  | namespace sw { | 
|  |  | 
|  | unsigned int Clipper::ComputeClipFlags(const float4 &v) | 
|  | { | 
|  | return ((v.x > v.w) ? CLIP_RIGHT : 0) | | 
|  | ((v.y > v.w) ? CLIP_TOP : 0) | | 
|  | ((v.z > v.w) ? CLIP_FAR : 0) | | 
|  | ((v.x < -v.w) ? CLIP_LEFT : 0) | | 
|  | ((v.y < -v.w) ? CLIP_BOTTOM : 0) | | 
|  | ((v.z < 0) ? CLIP_NEAR : 0) | | 
|  | Clipper::CLIP_FINITE;  // FIXME: xyz finite | 
|  | } | 
|  |  | 
|  | bool Clipper::Clip(Polygon &polygon, int clipFlagsOr, const DrawCall &draw) | 
|  | { | 
|  | if(clipFlagsOr & CLIP_FRUSTUM) | 
|  | { | 
|  | if(clipFlagsOr & CLIP_NEAR) clipNear(polygon); | 
|  | if(polygon.n >= 3) | 
|  | { | 
|  | if(clipFlagsOr & CLIP_FAR) clipFar(polygon); | 
|  | if(polygon.n >= 3) | 
|  | { | 
|  | if(clipFlagsOr & CLIP_LEFT) clipLeft(polygon); | 
|  | if(polygon.n >= 3) | 
|  | { | 
|  | if(clipFlagsOr & CLIP_RIGHT) clipRight(polygon); | 
|  | if(polygon.n >= 3) | 
|  | { | 
|  | if(clipFlagsOr & CLIP_TOP) clipTop(polygon); | 
|  | if(polygon.n >= 3) | 
|  | { | 
|  | if(clipFlagsOr & CLIP_BOTTOM) clipBottom(polygon); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return polygon.n >= 3; | 
|  | } | 
|  |  | 
|  | }  // namespace sw |