/
TransformUnit.h
185 lines (143 loc) · 5.4 KB
/
TransformUnit.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// 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 "CommonTypes.h"
#include "GPU/Common/DrawEngineCommon.h"
#include "GPU/Common/GPUDebugInterface.h"
#include "GPU/Software/SoftGpu.h"
#include "GPU/Math3D.h"
using namespace Math3D;
static constexpr int32_t SCREEN_SCALE_FACTOR = 16;
typedef u16 u10; // TODO: erm... :/
typedef Vec3<float> ModelCoords;
typedef Vec3<float> WorldCoords;
typedef Vec3<float> ViewCoords;
typedef Vec4<float> ClipCoords; // Range: -w <= x/y/z <= w
class BinManager;
struct TransformState;
enum class CullType {
CW = 0,
CCW = 1,
OFF = 2,
};
struct ScreenCoords
{
ScreenCoords() {}
ScreenCoords(int x, int y, u16 z) : x(x), y(y), z(z) {}
int x;
int y;
u16 z;
Vec2<int> xy() const { return Vec2<int>(x, y); }
ScreenCoords operator * (const float t) const
{
return ScreenCoords((int)(x * t), (int)(y * t), (u16)(z * t));
}
ScreenCoords operator / (const int t) const
{
return ScreenCoords(x / t, y / t, z / t);
}
ScreenCoords operator + (const ScreenCoords& oth) const
{
return ScreenCoords(x + oth.x, y + oth.y, z + oth.z);
}
};
struct DrawingCoords {
DrawingCoords() {}
DrawingCoords(s16 x, s16 y) : x(x), y(y) {}
s16 x;
s16 y;
};
struct VertexData {
void Lerp(float t, const VertexData &a, const VertexData &b) {
clippos = ::Lerp(a.clippos, b.clippos, t);
// Ignore screenpos because Lerp() is only used pre-calculation of screenpos.
texturecoords = ::Lerp(a.texturecoords, b.texturecoords, t);
fogdepth = ::Lerp(a.fogdepth, b.fogdepth, t);
u16 t_int = (u16)(t * 256);
color0 = LerpInt<Vec4<int>, 256>(Vec4<int>::FromRGBA(a.color0), Vec4<int>::FromRGBA(b.color0), t_int).ToRGBA();
color1 = LerpInt<Vec3<int>, 256>(Vec3<int>::FromRGB(a.color1), Vec3<int>::FromRGB(b.color1), t_int).ToRGB();
}
bool OutsideRange() const {
return screenpos.x == 0x7FFFFFFF;
}
ClipCoords clippos;
Vec2<float> texturecoords;
uint32_t color0;
uint32_t color1;
ScreenCoords screenpos; // TODO: Shouldn't store this ?
float fogdepth;
};
class VertexReader;
class SoftwareDrawEngine;
class TransformUnit {
public:
TransformUnit();
~TransformUnit();
static WorldCoords ModelToWorldNormal(const ModelCoords& coords);
static WorldCoords ModelToWorld(const ModelCoords& coords);
static ViewCoords WorldToView(const WorldCoords& coords);
static ClipCoords ViewToClip(const ViewCoords& coords);
static ScreenCoords ClipToScreen(const ClipCoords& coords);
static inline DrawingCoords ScreenToDrawing(int x, int y) {
DrawingCoords ret;
// When offset > coord, this is negative and force-scissors.
ret.x = x / SCREEN_SCALE_FACTOR;
ret.y = y / SCREEN_SCALE_FACTOR;
return ret;
}
static inline DrawingCoords ScreenToDrawing(const ScreenCoords &coords) {
return ScreenToDrawing(coords.x, coords.y);
}
static ScreenCoords DrawingToScreen(const DrawingCoords &coords, u16 z);
void SubmitPrimitive(const void* vertices, const void* indices, GEPrimitiveType prim_type, int vertex_count, u32 vertex_type, int *bytesRead, SoftwareDrawEngine *drawEngine);
void SubmitImmVertex(const VertexData &vert, SoftwareDrawEngine *drawEngine);
bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices);
void Flush(const char *reason);
void FlushIfOverlap(const char *reason, bool modifying, uint32_t addr, uint32_t stride, uint32_t w, uint32_t h);
void NotifyClutUpdate(const void *src);
void GetStats(char *buffer, size_t bufsize);
void SetDirty(SoftDirty flags);
SoftDirty GetDirty();
private:
VertexData ReadVertex(VertexReader &vreader, const TransformState &state);
void SendTriangle(CullType cullType, const VertexData *verts, int provoking = 2);
u8 *decoded_ = nullptr;
BinManager *binner_ = nullptr;
// Normally max verts per prim is 3, but we temporarily need 4 to detect rectangles from strips.
VertexData data_[4];
// This is the index of the next vert in data (or higher, may need modulus.)
int data_index_ = 0;
GEPrimitiveType prev_prim_ = GE_PRIM_POINTS;
bool hasDraws_ = false;
bool isImmDraw_ = false;
};
class SoftwareDrawEngine : public DrawEngineCommon {
public:
SoftwareDrawEngine();
~SoftwareDrawEngine();
void DispatchFlush() override;
void DispatchSubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int cullMode, int *bytesRead) override;
void DispatchSubmitImm(GEPrimitiveType prim, TransformedVertex *buffer, int vertexCount, int cullMode) override;
VertexDecoder *FindVertexDecoder(u32 vtype);
TransformUnit transformUnit;
#if PPSSPP_ARCH(32BIT)
void *operator new(size_t s) {
return AllocateAlignedMemory(s, 16);
}
void operator delete(void *p) {
FreeAlignedMemory(p);
}
#endif
protected:
bool UpdateUseHWTessellation(bool enable) override { return false; }
};