Add SwiftShader source to repo
Oct 6 code drop from Transgaming
Review URL: https://chromereviews.googleplex.com/3846015
diff --git a/src/Renderer/Clipper.cpp b/src/Renderer/Clipper.cpp
new file mode 100644
index 0000000..2c6c158
--- /dev/null
+++ b/src/Renderer/Clipper.cpp
@@ -0,0 +1,374 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2011 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+#include "Clipper.hpp"
+
+#include "Polygon.hpp"
+#include "Renderer.hpp"
+#include "Debug.hpp"
+
+#include <malloc.h>
+#include <assert.h>
+
+namespace sw
+{
+ Clipper::Clipper()
+ {
+ }
+
+ Clipper::~Clipper()
+ {
+ }
+
+ bool Clipper::clip(Polygon &polygon, int clipFlagsOr, const DrawCall &draw)
+ {
+ DrawData &data = *draw.data;
+
+ polygon.b = 0;
+
+ if(clipFlagsOr & 0x0000003F)
+ {
+ 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, data);
+ if(polygon.n >= 3) {
+ if(clipFlagsOr & CLIP_RIGHT) clipRight(polygon, data);
+ if(polygon.n >= 3) {
+ if(clipFlagsOr & CLIP_TOP) clipTop(polygon, data);
+ if(polygon.n >= 3) {
+ if(clipFlagsOr & CLIP_BOTTOM) clipBottom(polygon, data);
+ }}}}}
+ }
+
+ if(clipFlagsOr & 0x00003F00)
+ {
+ if(polygon.n >= 3) {
+ if(draw.clipFlags & CLIP_PLANE0) clipPlane(polygon, data.clipPlane[0]);
+ if(polygon.n >= 3) {
+ if(draw.clipFlags & CLIP_PLANE1) clipPlane(polygon, data.clipPlane[1]);
+ if(polygon.n >= 3) {
+ if(draw.clipFlags & CLIP_PLANE2) clipPlane(polygon, data.clipPlane[2]);
+ if(polygon.n >= 3) {
+ if(draw.clipFlags & CLIP_PLANE3) clipPlane(polygon, data.clipPlane[3]);
+ if(polygon.n >= 3) {
+ if(draw.clipFlags & CLIP_PLANE4) clipPlane(polygon, data.clipPlane[4]);
+ if(polygon.n >= 3) {
+ if(draw.clipFlags & CLIP_PLANE5) clipPlane(polygon, data.clipPlane[5]);
+ }}}}}}
+ }
+
+ return polygon.n >= 3;
+ }
+
+ void Clipper::clipNear(Polygon &polygon)
+ {
+ if(polygon.n == 0) return;
+
+ const float4 **V = polygon.P[polygon.i];
+ const 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);
+ polygon.B[polygon.b].z = 0;
+ T[t++] = &polygon.B[polygon.b++];
+ }
+ }
+ else
+ {
+ if(dj > 0)
+ {
+ clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
+ polygon.B[polygon.b].z = 0;
+ T[t++] = &polygon.B[polygon.b++];
+ }
+ }
+ }
+
+ polygon.n = t;
+ polygon.i += 1;
+ }
+
+ void Clipper::clipFar(Polygon &polygon)
+ {
+ if(polygon.n == 0) return;
+
+ const float4 **V = polygon.P[polygon.i];
+ const 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);
+ polygon.B[polygon.b].z = polygon.B[polygon.b].w;
+ T[t++] = &polygon.B[polygon.b++];
+ }
+ }
+ else
+ {
+ if(dj > 0)
+ {
+ clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
+ polygon.B[polygon.b].z = polygon.B[polygon.b].w;
+ T[t++] = &polygon.B[polygon.b++];
+ }
+ }
+ }
+
+ polygon.n = t;
+ polygon.i += 1;
+ }
+
+ void Clipper::clipLeft(Polygon &polygon, const DrawData &data)
+ {
+ if(polygon.n == 0) return;
+
+ const float4 **V = polygon.P[polygon.i];
+ const 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 + data.offX[0] * V[i]->w);
+ float dj = V[j]->w + (V[j]->x + data.offX[0] * V[j]->w);
+
+ if(di >= 0)
+ {
+ T[t++] = V[i];
+
+ if(dj < 0)
+ {
+ clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
+ // polygon.B[polygon.b].x = -polygon.B[polygon.b].w;
+ T[t++] = &polygon.B[polygon.b++];
+ }
+ }
+ else
+ {
+ if(dj > 0)
+ {
+ clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
+ // polygon.B[polygon.b].x = -polygon.B[polygon.b].w;
+ T[t++] = &polygon.B[polygon.b++];
+ }
+ }
+ }
+
+ polygon.n = t;
+ polygon.i += 1;
+ }
+
+ void Clipper::clipRight(Polygon &polygon, const DrawData &data)
+ {
+ if(polygon.n == 0) return;
+
+ const float4 **V = polygon.P[polygon.i];
+ const 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 + data.offX[0] * V[i]->w);
+ float dj = V[j]->w - (V[j]->x + data.offX[0] * V[j]->w);
+
+ if(di >= 0)
+ {
+ T[t++] = V[i];
+
+ if(dj < 0)
+ {
+ clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
+ // polygon.B[polygon.b].x = polygon.B[polygon.b].w;
+ T[t++] = &polygon.B[polygon.b++];
+ }
+ }
+ else
+ {
+ if(dj > 0)
+ {
+ clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
+ // polygon.B[polygon.b].x = polygon.B[polygon.b].w;
+ T[t++] = &polygon.B[polygon.b++];
+ }
+ }
+ }
+
+ polygon.n = t;
+ polygon.i += 1;
+ }
+
+ void Clipper::clipTop(Polygon &polygon, const DrawData &data)
+ {
+ if(polygon.n == 0) return;
+
+ const float4 **V = polygon.P[polygon.i];
+ const 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 + data.offY[0] * V[i]->w);
+ float dj = V[j]->w - (V[j]->y + data.offY[0] * V[j]->w);
+
+ if(di >= 0)
+ {
+ T[t++] = V[i];
+
+ if(dj < 0)
+ {
+ clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
+ // polygon.B[polygon.b].y = polygon.B[polygon.b].w;
+ T[t++] = &polygon.B[polygon.b++];
+ }
+ }
+ else
+ {
+ if(dj > 0)
+ {
+ clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
+ // polygon.B[polygon.b].y = polygon.B[polygon.b].w;
+ T[t++] = &polygon.B[polygon.b++];
+ }
+ }
+ }
+
+ polygon.n = t;
+ polygon.i += 1;
+ }
+
+ void Clipper::clipBottom(Polygon &polygon, const DrawData &data)
+ {
+ if(polygon.n == 0) return;
+
+ const float4 **V = polygon.P[polygon.i];
+ const 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 + data.offY[0] * V[i]->w);
+ float dj = V[j]->w + (V[j]->y + data.offY[0] * V[j]->w);
+
+ if(di >= 0)
+ {
+ T[t++] = V[i];
+
+ if(dj < 0)
+ {
+ clipEdge(polygon.B[polygon.b], *V[i], *V[j], di, dj);
+ // polygon.B[polygon.b].y = -polygon.B[polygon.b].w;
+ T[t++] = &polygon.B[polygon.b++];
+ }
+ }
+ else
+ {
+ if(dj > 0)
+ {
+ clipEdge(polygon.B[polygon.b], *V[j], *V[i], dj, di);
+ // polygon.B[polygon.b].y = -polygon.B[polygon.b].w;
+ T[t++] = &polygon.B[polygon.b++];
+ }
+ }
+ }
+
+ polygon.n = t;
+ polygon.i += 1;
+ }
+
+ void Clipper::clipPlane(Polygon &polygon, const Plane &p)
+ {
+ if(polygon.n == 0) return;
+
+ const float4 **V = polygon.P[polygon.i];
+ const 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 = p.A * V[i]->x + p.B * V[i]->y + p.C * V[i]->z + p.D * V[i]->w;
+ float dj = p.A * V[j]->x + p.B * V[j]->y + p.C * V[j]->z + p.D * V[j]->w;
+
+ 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;
+ }
+
+ inline void Clipper::clipEdge(float4 &Vo, const float4 &Vi, const float4 &Vj, float di, float dj) const
+ {
+ 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;
+ }
+}