diff --git a/CMakeLists.txt b/CMakeLists.txt
index 78bdd34677..872b0ede45 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1015,12 +1015,14 @@ add_library(GPU OBJECT
GPU/Math3D.h
GPU/Null/NullGpu.cpp
GPU/Null/NullGpu.h
+ GPU/Software/Clipper.cpp
+ GPU/Software/Clipper.h
+ GPU/Software/Rasterizer.cpp
+ GPU/Software/Rasterizer.h
GPU/Software/SoftGpu.cpp
GPU/Software/SoftGpu.h
GPU/Software/TransformUnit.cpp
GPU/Software/TransformUnit.h
- GPU/Software/Rasterizer.cpp
- GPU/Software/Rasterizer.h
GPU/ge_constants.h)
setup_target_project(GPU GPU)
diff --git a/GPU/CMakeLists.txt b/GPU/CMakeLists.txt
index 3fc202f2ce..5710379d5f 100644
--- a/GPU/CMakeLists.txt
+++ b/GPU/CMakeLists.txt
@@ -14,6 +14,7 @@ set(SRCS
GLES/VertexDecoder.cpp
GLES/VertexShaderGenerator.cpp
Null/NullGpu.cpp
+ Software/Clipper.cpp
Software/Rasterizer.cpp
Software/SoftGpu.cpp
Software/TransformUnit.cpp
diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj
index 74a39941c9..1a6fe6e41a 100644
--- a/GPU/GPU.vcxproj
+++ b/GPU/GPU.vcxproj
@@ -162,6 +162,7 @@
+
@@ -186,6 +187,7 @@
+
diff --git a/GPU/GPU.vcxproj.filters b/GPU/GPU.vcxproj.filters
index 6dd46c9121..04f8c18fe9 100644
--- a/GPU/GPU.vcxproj.filters
+++ b/GPU/GPU.vcxproj.filters
@@ -68,6 +68,9 @@
GLES
+
+ Software
+
Software
@@ -126,6 +129,9 @@
GLES
+
+ Software
+
Software
diff --git a/GPU/Software/Clipper.cpp b/GPU/Software/Clipper.cpp
new file mode 100644
index 0000000000..adcc1543c8
--- /dev/null
+++ b/GPU/Software/Clipper.cpp
@@ -0,0 +1,170 @@
+// Copyright (c) 2013- PPSSPP Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0 or later versions.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official git repository and contact information can be found at
+// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
+
+#include "Clipper.h"
+#include "Rasterizer.h"
+
+namespace Clipper {
+
+enum {
+ SKIP_FLAG = -1,
+ CLIP_POS_X_BIT = 0x01,
+ CLIP_NEG_X_BIT = 0x02,
+ CLIP_POS_Y_BIT = 0x04,
+ CLIP_NEG_Y_BIT = 0x08,
+ CLIP_POS_Z_BIT = 0x10,
+ CLIP_NEG_Z_BIT = 0x20,
+};
+
+static inline int CalcClipMask(const ClipCoords& v)
+{
+ int mask = 0;
+ if (v.x > v.w) mask |= CLIP_POS_X_BIT;
+ if (v.x < -v.w) mask |= CLIP_NEG_X_BIT;
+ if (v.y > v.w) mask |= CLIP_POS_Y_BIT;
+ if (v.y < -v.w) mask |= CLIP_NEG_Y_BIT;
+ if (v.z > v.w) mask |= CLIP_POS_Z_BIT;
+ if (v.z < -v.w) mask |= CLIP_NEG_Z_BIT;
+ return mask;
+}
+
+#define AddInterpolatedVertex(t, out, in, numVertices) \
+{ \
+ Vertices[numVertices]->Lerp(t, *Vertices[out], *Vertices[in]); \
+ numVertices++; \
+}
+
+#define DIFFERENT_SIGNS(x,y) ((x <= 0 && y > 0) || (x > 0 && y <= 0))
+
+#define CLIP_DOTPROD(I, A, B, C, D) \
+ (Vertices[I]->clippos.x * A + Vertices[I]->clippos.y * B + Vertices[I]->clippos.z * C + Vertices[I]->clippos.w * D)
+
+#define POLY_CLIP( PLANE_BIT, A, B, C, D ) \
+{ \
+ if (mask & PLANE_BIT) { \
+ int idxPrev = inlist[0]; \
+ float dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
+ int outcount = 0; \
+ \
+ inlist[n] = inlist[0]; \
+ for (int j = 1; j <= n; j++) { \
+ int idx = inlist[j]; \
+ float dp = CLIP_DOTPROD(idx, A, B, C, D ); \
+ if (dpPrev >= 0) { \
+ outlist[outcount++] = idxPrev; \
+ } \
+ \
+ if (DIFFERENT_SIGNS(dp, dpPrev)) { \
+ if (dp < 0) { \
+ float t = dp / (dp - dpPrev); \
+ AddInterpolatedVertex(t, idx, idxPrev, numVertices); \
+ } else { \
+ float t = dpPrev / (dpPrev - dp); \
+ AddInterpolatedVertex(t, idxPrev, idx, numVertices); \
+ } \
+ outlist[outcount++] = numVertices - 1; \
+ } \
+ \
+ idxPrev = idx; \
+ dpPrev = dp; \
+ } \
+ \
+ if (outcount < 3) \
+ continue; \
+ \
+ { \
+ int *tmp = inlist; \
+ inlist = outlist; \
+ outlist = tmp; \
+ n = outcount; \
+ } \
+ } \
+}
+
+void ProcessTriangle(VertexData* data)
+{
+ enum { NUM_CLIPPED_VERTICES = 33, NUM_INDICES = NUM_CLIPPED_VERTICES + 3 };
+
+ VertexData* Vertices[NUM_CLIPPED_VERTICES];
+ VertexData ClippedVertices[NUM_CLIPPED_VERTICES];
+ for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i)
+ Vertices[i+3] = &ClippedVertices[i];
+
+ // TODO: Change logic when it's a backface
+ Vertices[0] = &data[0];
+ Vertices[1] = &data[1];
+ Vertices[2] = &data[2];
+
+ int indices[NUM_INDICES] = { 0, 1, 2, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
+ SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
+ SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG };
+ int numIndices = 3;
+
+ int mask = 0;
+ mask |= CalcClipMask(data[0].clippos);
+ mask |= CalcClipMask(data[1].clippos);
+ mask |= CalcClipMask(data[2].clippos);
+
+ if (mask) {
+ for(int i = 0; i < 3; i += 3) {
+ int vlist[2][2*6+1];
+ int *inlist = vlist[0], *outlist = vlist[1];
+ int n = 3;
+ int numVertices = 3;
+
+ inlist[0] = 0;
+ inlist[1] = 1;
+ inlist[2] = 2;
+
+ // mark this triangle as unused in case it should be completely clipped
+ indices[0] = SKIP_FLAG;
+ indices[1] = SKIP_FLAG;
+ indices[2] = SKIP_FLAG;
+
+ POLY_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1);
+ POLY_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1);
+ POLY_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1);
+ POLY_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1);
+ POLY_CLIP(CLIP_POS_Z_BIT, 0, 0, 0, 1);
+ POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
+
+ // transform the poly in inlist into triangles
+ indices[0] = inlist[0];
+ indices[1] = inlist[1];
+ indices[2] = inlist[2];
+ for (int j = 3; j < n; ++j) {
+ indices[numIndices++] = inlist[0];
+ indices[numIndices++] = inlist[j - 1];
+ indices[numIndices++] = inlist[j];
+ }
+ }
+ }
+
+ for(int i = 0; i+3 <= numIndices; i+=3)
+ {
+ if(indices[i] != SKIP_FLAG)
+ {
+ VertexData data[3] = { *Vertices[indices[i]], *Vertices[indices[i+1]], *Vertices[indices[i+2]] };
+ data[0].drawpos = DrawingCoords(TransformUnit::ScreenToDrawing(TransformUnit::ClipToScreen(data[0].clippos)));
+ data[1].drawpos = DrawingCoords(TransformUnit::ScreenToDrawing(TransformUnit::ClipToScreen(data[1].clippos)));
+ data[2].drawpos = DrawingCoords(TransformUnit::ScreenToDrawing(TransformUnit::ClipToScreen(data[2].clippos)));
+ Rasterizer::DrawTriangle(data);
+ }
+ }
+}
+
+} // namespace
diff --git a/GPU/Software/Clipper.h b/GPU/Software/Clipper.h
new file mode 100644
index 0000000000..c8f84efd77
--- /dev/null
+++ b/GPU/Software/Clipper.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2013- PPSSPP Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0 or later versions.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official git repository and contact information can be found at
+// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
+
+#pragma once
+
+#include "TransformUnit.h"
+
+namespace Clipper {
+
+void ProcessTriangle(VertexData* data);
+
+}
diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp
index 369670b801..5135805de5 100644
--- a/GPU/Software/TransformUnit.cpp
+++ b/GPU/Software/TransformUnit.cpp
@@ -19,7 +19,7 @@
#include "../GLES/VertexDecoder.h"
#include "TransformUnit.h"
-#include "Rasterizer.h"
+#include "Clipper.h"
WorldCoords TransformUnit::ModelToWorld(const ModelCoords& coords)
{
@@ -60,88 +60,11 @@ DrawingCoords TransformUnit::ScreenToDrawing(const ScreenCoords& coords)
{
DrawingCoords ret;
// TODO: What to do when offset > coord?
- // TODO: Mask can be re-enabled now, I guess.
ret.x = (((u32)coords.x - (gstate.offsetx&0xffff))/16) & 0x3ff;
ret.y = (((u32)coords.y - (gstate.offsety&0xffff))/16) & 0x3ff;
return ret;
}
-enum {
- SKIP_FLAG = -1,
- CLIP_POS_X_BIT = 0x01,
- CLIP_NEG_X_BIT = 0x02,
- CLIP_POS_Y_BIT = 0x04,
- CLIP_NEG_Y_BIT = 0x08,
- CLIP_POS_Z_BIT = 0x10,
- CLIP_NEG_Z_BIT = 0x20,
-};
-
-static inline int CalcClipMask(const ClipCoords& v)
-{
- int mask = 0;
- // TODO: Do we need to include the equal sign here, too?
- if (v.x > v.w) mask |= CLIP_POS_X_BIT;
- if (v.x < -v.w) mask |= CLIP_NEG_X_BIT;
- if (v.y > v.w) mask |= CLIP_POS_Y_BIT;
- if (v.y < -v.w) mask |= CLIP_NEG_Y_BIT;
- if (v.z > v.w) mask |= CLIP_POS_Z_BIT;
- if (v.z < -v.w) mask |= CLIP_NEG_Z_BIT;
- return mask;
-}
-
-#define AddInterpolatedVertex(t, out, in, numVertices) \
-{ \
- Vertices[numVertices]->Lerp(t, *Vertices[out], *Vertices[in]); \
- numVertices++; \
-}
-
-#define DIFFERENT_SIGNS(x,y) ((x <= 0 && y > 0) || (x > 0 && y <= 0))
-
-#define CLIP_DOTPROD(I, A, B, C, D) \
- (Vertices[I]->clippos.x * A + Vertices[I]->clippos.y * B + Vertices[I]->clippos.z * C + Vertices[I]->clippos.w * D)
-
-#define POLY_CLIP( PLANE_BIT, A, B, C, D ) \
-{ \
- if (mask & PLANE_BIT) { \
- int idxPrev = inlist[0]; \
- float dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
- int outcount = 0; \
- \
- inlist[n] = inlist[0]; \
- for (int j = 1; j <= n; j++) { \
- int idx = inlist[j]; \
- float dp = CLIP_DOTPROD(idx, A, B, C, D ); \
- if (dpPrev >= 0) { \
- outlist[outcount++] = idxPrev; \
- } \
- \
- if (DIFFERENT_SIGNS(dp, dpPrev)) { \
- if (dp < 0) { \
- float t = dp / (dp - dpPrev); \
- AddInterpolatedVertex(t, idx, idxPrev, numVertices); \
- } else { \
- float t = dpPrev / (dpPrev - dp); \
- AddInterpolatedVertex(t, idxPrev, idx, numVertices); \
- } \
- outlist[outcount++] = numVertices - 1; \
- } \
- \
- idxPrev = idx; \
- dpPrev = dp; \
- } \
- \
- if (outcount < 3) \
- continue; \
- \
- { \
- int *tmp = inlist; \
- inlist = outlist; \
- outlist = tmp; \
- n = outcount; \
- } \
- } \
-}
-
void TransformUnit::SubmitPrimitive(void* vertices, u32 prim_type, int vertex_count, u32 vertex_type)
{
// TODO: Cache VertexDecoder objects
@@ -157,19 +80,8 @@ void TransformUnit::SubmitPrimitive(void* vertices, u32 prim_type, int vertex_co
// We only support triangle lists, for now.
for (int vtx = 0; vtx < vertex_count; vtx+=3)
{
- enum { NUM_CLIPPED_VERTICES = 33, NUM_INDICES = NUM_CLIPPED_VERTICES + 3 };
- VertexData* Vertices[NUM_CLIPPED_VERTICES];
- VertexData ClippedVertices[NUM_CLIPPED_VERTICES];
VertexData data[3];
- for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i)
- Vertices[i+3] = &ClippedVertices[i];
-
- // TODO: Change logic when it's a backface
- Vertices[0] = &data[0];
- Vertices[1] = &data[1];
- Vertices[2] = &data[2];
-
for (unsigned int i = 0; i < 3; ++i)
{
float pos[3];
@@ -190,62 +102,6 @@ void TransformUnit::SubmitPrimitive(void* vertices, u32 prim_type, int vertex_co
// TODO: Should do lighting here!
- int indices[NUM_INDICES] = { 0, 1, 2, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
- SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
- SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG };
- int numIndices = 3;
-
- int mask = 0;
- mask |= CalcClipMask(data[0].clippos);
- mask |= CalcClipMask(data[1].clippos);
- mask |= CalcClipMask(data[2].clippos);
-
- if (mask) {
- for(int i = 0; i < 3; i += 3) {
- int vlist[2][2*6+1];
- int *inlist = vlist[0], *outlist = vlist[1];
- int n = 3;
- int numVertices = 3;
-
- inlist[0] = 0;
- inlist[1] = 1;
- inlist[2] = 2;
-
- // mark this triangle as unused in case it should be completely clipped
- indices[0] = SKIP_FLAG;
- indices[1] = SKIP_FLAG;
- indices[2] = SKIP_FLAG;
-
- POLY_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1);
- POLY_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1);
- POLY_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1);
- POLY_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1);
- POLY_CLIP(CLIP_POS_Z_BIT, 0, 0, 0, 1);
- POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
-
- // transform the poly in inlist into triangles
- indices[0] = inlist[0];
- indices[1] = inlist[1];
- indices[2] = inlist[2];
- for (int j = 3; j < n; ++j) {
- indices[numIndices++] = inlist[0];
- indices[numIndices++] = inlist[j - 1];
- indices[numIndices++] = inlist[j];
- }
- }
- }
-
- for(int i = 0; i+3 <= numIndices; i+=3)
- {
- if(indices[i] != SKIP_FLAG)
- {
- VertexData data[3] = { *Vertices[indices[i]], *Vertices[indices[i+1]], *Vertices[indices[i+2]] };
- data[0].drawpos = DrawingCoords(TransformUnit::ScreenToDrawing(TransformUnit::ClipToScreen(data[0].clippos)));
- data[1].drawpos = DrawingCoords(TransformUnit::ScreenToDrawing(TransformUnit::ClipToScreen(data[1].clippos)));
- data[2].drawpos = DrawingCoords(TransformUnit::ScreenToDrawing(TransformUnit::ClipToScreen(data[2].clippos)));
- Rasterizer::DrawTriangle(data);
- }
- }
-skip:;
+ Clipper::ProcessTriangle(data);
}
}