Skip to content

Commit baaf19c

Browse files
committed
gpu: refactored polygon command to output valid struct
1 parent 8bfa8ad commit baaf19c

File tree

12 files changed

+343
-334
lines changed

12 files changed

+343
-334
lines changed

src/device/gpu/gpu.cpp

Lines changed: 61 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -46,60 +46,32 @@ void GPU::reset() {
4646
gp0_e6._reg = 0;
4747
}
4848

49-
void GPU::drawPolygon(int16_t x[4], int16_t y[4], RGB c[4], TextureInfo t, bool isQuad, bool textured, int flags) {
50-
int baseX = 0, baseY = 0, clutX = 0, clutY = 0, bitcount = 0;
51-
52-
for (int i = 0; i < (isQuad ? 4 : 3); i++) {
53-
x[i] += drawingOffsetX;
54-
y[i] += drawingOffsetY;
55-
}
56-
57-
if (textured) {
58-
clutX = t.getClutX();
59-
clutY = t.getClutY();
60-
baseX = t.getBaseX();
61-
baseY = t.getBaseY();
62-
bitcount = t.getBitcount();
63-
flags |= ((int)t.semiTransparencyBlending()) << 5;
64-
} else {
65-
flags |= ((int)gp0_e1.semiTransparency) << 5;
49+
void GPU::drawTriangle(const primitive::Triangle& triangle) {
50+
if (hardwareRendering) {
51+
int flags = 0;
52+
if (triangle.isSemiTransparent) flags |= Vertex::Flags::SemiTransparency;
53+
if (triangle.isRawTexture) flags |= Vertex::Flags::RawTexture;
54+
if (gp0_e1.dither24to15) flags |= Vertex::Flags::Dithering;
55+
if (triangle.gouroudShading) flags |= Vertex::Flags::GouroudShading;
56+
flags |= static_cast<int>(triangle.transparency) << 5;
57+
58+
for (int i : {0, 1, 2}) {
59+
auto& v = triangle.v[i];
60+
vertices.push_back({Vertex::Type::Polygon,
61+
{v.pos.x + drawingOffsetX, v.pos.y + drawingOffsetY},
62+
{v.color.r, v.color.g, v.color.b},
63+
{v.uv.x, v.uv.y},
64+
triangle.bits,
65+
{triangle.clut.x, triangle.clut.y},
66+
{triangle.texpage.x, triangle.texpage.y},
67+
flags,
68+
gp0_e2,
69+
gp0_e6});
70+
}
6671
}
6772

68-
Vertex v[3];
69-
for (int i : {0, 1, 2}) {
70-
v[i] = {Vertex::Type::Polygon,
71-
{x[i], y[i]},
72-
{c[i].r, c[i].g, c[i].b},
73-
{t.uv[i].x, t.uv[i].y},
74-
bitcount,
75-
{clutX, clutY},
76-
{baseX, baseY},
77-
flags,
78-
gp0_e2,
79-
gp0_e6};
80-
vertices.push_back(v[i]);
81-
}
8273
if (softwareRendering) {
83-
Render::drawTriangle(this, v);
84-
}
85-
86-
if (isQuad) {
87-
for (int i : {1, 2, 3}) {
88-
v[i - 1] = {Vertex::Type::Polygon,
89-
{x[i], y[i]},
90-
{c[i].r, c[i].g, c[i].b},
91-
{t.uv[i].x, t.uv[i].y},
92-
bitcount,
93-
{clutX, clutY},
94-
{baseX, baseY},
95-
flags,
96-
gp0_e2,
97-
gp0_e6};
98-
vertices.push_back(v[i - 1]);
99-
}
100-
if (softwareRendering) {
101-
Render::drawTriangle(this, v);
102-
}
74+
Render::drawTriangle(this, triangle);
10375
}
10476
}
10577

@@ -241,29 +213,53 @@ void GPU::cmdFillRectangle(uint8_t command) {
241213

242214
void GPU::cmdPolygon(PolygonArgs arg) {
243215
int ptr = 1;
244-
int16_t x[4], y[4];
245-
RGB c[4] = {};
216+
217+
primitive::Triangle::Vertex v[4];
246218
TextureInfo tex;
219+
247220
for (int i = 0; i < arg.getVertexCount(); i++) {
248-
x[i] = extend_sign<10>(arguments[ptr] & 0xffff);
249-
y[i] = extend_sign<10>((arguments[ptr++] & 0xffff0000) >> 16);
221+
v[i].pos.x = extend_sign<10>(arguments[ptr] & 0xffff);
222+
v[i].pos.y = extend_sign<10>((arguments[ptr++] & 0xffff0000) >> 16);
250223

251-
if (!arg.isRawTexture && (!arg.gouroudShading || i == 0)) c[i].raw = arguments[0] & 0xffffff;
224+
if (!arg.isRawTexture && (!arg.gouroudShading || i == 0)) v[i].color.raw = arguments[0] & 0xffffff;
252225
if (arg.isTextureMapped) {
253226
if (i == 0) tex.palette = arguments[ptr];
254227
if (i == 1) tex.texpage = arguments[ptr];
255-
tex.uv[i].x = arguments[ptr] & 0xff;
256-
tex.uv[i].y = (arguments[ptr] >> 8) & 0xff;
228+
v[i].uv.x = arguments[ptr] & 0xff;
229+
v[i].uv.y = (arguments[ptr] >> 8) & 0xff;
257230
ptr++;
258231
}
259-
if (arg.gouroudShading && i < arg.getVertexCount() - 1) c[i + 1].raw = arguments[ptr++];
232+
if (arg.gouroudShading && i < arg.getVertexCount() - 1) v[i + 1].color.raw = arguments[ptr++] & 0xffffff;
233+
}
234+
235+
primitive::Triangle triangle;
236+
237+
for (int i : {0, 1, 2}) triangle.v[i] = v[i];
238+
239+
triangle.bits = 0;
240+
triangle.isSemiTransparent = arg.semiTransparency;
241+
triangle.transparency = gp0_e1.semiTransparency;
242+
triangle.isRawTexture = arg.isRawTexture;
243+
triangle.gouroudShading = arg.gouroudShading;
244+
245+
if (arg.isTextureMapped) {
246+
triangle.bits = tex.getBitcount();
247+
triangle.texpage.x = tex.getBaseX();
248+
triangle.texpage.y = tex.getBaseY();
249+
triangle.clut.x = tex.getClutX();
250+
triangle.clut.y = tex.getClutY();
251+
triangle.transparency = tex.semiTransparencyBlending();
252+
}
253+
254+
triangle.assureCcw();
255+
drawTriangle(triangle);
256+
257+
if (arg.isQuad) {
258+
for (int i : {1, 2, 3}) triangle.v[i - 1] = v[i];
259+
260+
triangle.assureCcw();
261+
drawTriangle(triangle);
260262
}
261-
int flags = 0;
262-
if (arg.semiTransparency) flags |= Vertex::SemiTransparency;
263-
if (arg.isRawTexture) flags |= Vertex::RawTexture;
264-
if (arg.gouroudShading) flags |= Vertex::GouroudShading;
265-
if (gp0_e1.dither24to15) flags |= Vertex::Dithering;
266-
drawPolygon(x, y, c, tex, arg.isQuad, arg.isTextureMapped, flags);
267263

268264
cmd = Command::None;
269265
}

src/device/gpu/gpu.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ class GPU {
106106
void cmdVramToCpu(uint8_t command);
107107
void cmdVramToVram(uint8_t command);
108108

109-
void drawPolygon(int16_t x[4], int16_t y[4], RGB c[4], TextureInfo t, bool isQuad = false, bool textured = false, int flags = 0);
109+
void drawTriangle(const primitive::Triangle& triangle);
110110
void drawLine(const primitive::Line& line);
111111
void drawRectangle(const primitive::Rect& rect);
112112

src/device/gpu/primitive.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#pragma once
22
#include <glm/glm.hpp>
3+
#include <utility>
4+
#include "device/gpu/semi_transparency.h"
35
#include "psx_color.h"
46

57
namespace primitive {
@@ -27,4 +29,39 @@ struct Line {
2729
bool isSemiTransparent;
2830
bool gouroudShading;
2931
};
32+
33+
struct Triangle {
34+
struct Vertex {
35+
glm::ivec2 pos;
36+
RGB color; // Valid if bits == 0 or !isRawTexture
37+
glm::ivec2 uv; // Valid if bits != 0
38+
};
39+
Vertex v[3];
40+
41+
// Flags
42+
int bits = 0;
43+
gpu::SemiTransparency transparency; // Valid if isSemiTransparent
44+
bool isSemiTransparent = false;
45+
bool isRawTexture = false;
46+
bool gouroudShading = false;
47+
48+
// Texture, valid if bits != 0
49+
glm::ivec2 texpage; // Texture page position in VRAM
50+
glm::ivec2 clut; // Texture palette position in VRAM
51+
52+
void assureCcw() {
53+
if (isCw()) {
54+
std::swap(v[1], v[2]);
55+
}
56+
}
57+
58+
private:
59+
bool isCw() const {
60+
auto ab = v[1].pos - v[0].pos;
61+
auto ac = v[2].pos - v[0].pos;
62+
auto cross = ab.x * ac.y - ab.y * ac.x;
63+
64+
return cross < 0;
65+
}
66+
};
3067
} // namespace primitive

src/device/gpu/psx_color.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "utils/macros.h"
55
#include "utils/math.h"
66

7+
#undef RGB // Some header is adding this macro on Windows
78
// Union for storing 24bit color (used in GPU commands)
89
union RGB {
910
struct {
@@ -13,6 +14,8 @@ union RGB {
1314
uint8_t _;
1415
};
1516
uint32_t raw;
17+
18+
RGB() : raw(0) {}
1619
};
1720

1821
RGB operator*(const RGB& lhs, const float rhs);

src/device/gpu/registers.h

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22
#include "device/device.h"
3+
#include "semi_transparency.h"
34

45
namespace gpu {
56

@@ -8,12 +9,6 @@ const int MAX_ARGS = 32;
89

910
// Draw Mode setting
1011
union GP0_E1 {
11-
enum class SemiTransparency : uint32_t {
12-
Bby2plusFby2 = 0, // B/2+F/2
13-
BplusF = 1, // B+F
14-
BminusF = 2, // B-F
15-
BplusFby4 = 3 // B+F/4
16-
};
1712
enum class TexturePageColors : uint32_t { bit4 = 0, bit8 = 1, bit15 = 2 };
1813
enum class DrawingToDisplayArea : uint32_t { prohibited = 0, allowed = 1 };
1914
struct {
@@ -248,12 +243,8 @@ struct TextureInfo {
248243

249244
int getClutX() const { return ((palette & 0x003f0000) >> 16) * 16; }
250245
int getClutY() const { return ((palette & 0x7fc00000) >> 22); }
251-
int getBaseX() const {
252-
return ((texpage & 0x0f0000) >> 16) * 64; // N * 64
253-
}
254-
int getBaseY() const {
255-
return ((texpage & 0x100000) >> 20) * 256; // N * 256
256-
}
246+
int getBaseX() const { return ((texpage & 0x0f0000) >> 16) * 64; } // N * 64
247+
int getBaseY() const { return ((texpage & 0x100000) >> 20) * 256; } // N * 256
257248
int getBitcount() const {
258249
int depth = (texpage & 0x1800000) >> 23;
259250
switch (depth) {
@@ -265,7 +256,7 @@ struct TextureInfo {
265256
}
266257
}
267258

268-
GP0_E1::SemiTransparency semiTransparencyBlending() const { return (GP0_E1::SemiTransparency)((texpage & 0x600000) >> 21); }
259+
SemiTransparency semiTransparencyBlending() const { return (SemiTransparency)((texpage & 0x600000) >> 21); }
269260
};
270261

271262
// Debug/rewind

src/device/gpu/render/render.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
class Render {
55
public:
66
static void drawLine(gpu::GPU* gpu, const primitive::Line& line);
7-
static void drawTriangle(gpu::GPU* gpu, gpu::Vertex v[3]);
7+
static void drawTriangle(gpu::GPU* gpu, const primitive::Triangle& triangle);
88
static void drawRectangle(gpu::GPU* gpu, const primitive::Rect& rect);
99
};

src/device/gpu/render/render_line.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#define VRAM ((uint16_t(*)[gpu::VRAM_WIDTH])gpu->vram.data())
88

99
void Render::drawLine(gpu::GPU* gpu, const primitive::Line& line) {
10-
using Transparency = gpu::GP0_E1::SemiTransparency;
10+
using Transparency = gpu::SemiTransparency;
1111
const auto transparency = gpu->gp0_e1.semiTransparency;
1212
const bool checkMaskBeforeDraw = gpu->gp0_e6.checkMaskBeforeDraw;
1313
const bool setMaskWhileDrawing = gpu->gp0_e6.setMaskWhileDrawing;

0 commit comments

Comments
 (0)