mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-17 04:39:34 +00:00
softgpu: Move clipping code to a separate file.
This commit is contained in:
parent
b5181c9f4f
commit
2aff3a8575
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -162,6 +162,7 @@
|
||||
<ClInclude Include="GPUState.h" />
|
||||
<ClInclude Include="Math3D.h" />
|
||||
<ClInclude Include="Null\NullGpu.h" />
|
||||
<ClInclude Include="Software\Clipper.h" />
|
||||
<ClInclude Include="Software\Rasterizer.h" />
|
||||
<ClInclude Include="Software\SoftGpu.h" />
|
||||
<ClInclude Include="Software\TransformUnit.h" />
|
||||
@ -186,6 +187,7 @@
|
||||
<ClCompile Include="GPUState.cpp" />
|
||||
<ClCompile Include="Math3D.cpp" />
|
||||
<ClCompile Include="Null\NullGpu.cpp" />
|
||||
<ClCompile Include="Software\Clipper.cpp" />
|
||||
<ClCompile Include="Software\Rasterizer.cpp" />
|
||||
<ClCompile Include="Software\SoftGpu.cpp" />
|
||||
<ClCompile Include="Software\TransformUnit.cpp" />
|
||||
|
@ -68,6 +68,9 @@
|
||||
<ClInclude Include="GLES\TextureScaler.h">
|
||||
<Filter>GLES</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Software\Clipper.h">
|
||||
<Filter>Software</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Software\Rasterizer.h">
|
||||
<Filter>Software</Filter>
|
||||
</ClInclude>
|
||||
@ -126,6 +129,9 @@
|
||||
<ClCompile Include="GLES\TextureScaler.cpp">
|
||||
<Filter>GLES</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Software\Clipper.cpp">
|
||||
<Filter>Software</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Software\Rasterizer.cpp">
|
||||
<Filter>Software</Filter>
|
||||
</ClCompile>
|
||||
|
170
GPU/Software/Clipper.cpp
Normal file
170
GPU/Software/Clipper.cpp
Normal file
@ -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
|
26
GPU/Software/Clipper.h
Normal file
26
GPU/Software/Clipper.h
Normal file
@ -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);
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user