Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Windows/GEDebugger/VertexPreview.cpp
3185 views
1
// Copyright (c) 2013- PPSSPP Project.
2
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
6
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
11
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
14
15
// Official git repository and contact information can be found at
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18
#include "Common/Math/lin/matrix4x4.h"
19
#include "Common/GPU/OpenGL/GLSLProgram.h"
20
#include "Common/GPU/OpenGL/GLFeatures.h"
21
#include "Windows/GEDebugger/GEDebugger.h"
22
#include "Windows/GEDebugger/SimpleGLWindow.h"
23
#include "Core/System.h"
24
#include "Core/Config.h"
25
#include "GPU/GPUCommon.h"
26
#include "GPU/Common/GPUDebugInterface.h"
27
#include "GPU/Common/SplineCommon.h"
28
#include "GPU/Debugger/State.h"
29
#include "GPU/GPUState.h"
30
#include "Common/Log.h"
31
#include "Common/MemoryUtil.h"
32
33
static const char preview_fs[] =
34
"#ifdef GL_ES\n"
35
"precision mediump float;\n"
36
"#endif\n"
37
"void main() {\n"
38
" gl_FragColor = vec4(1.0, 0.0, 0.0, 0.6);\n"
39
"}\n";
40
41
static const char preview_vs[] =
42
"#version 120\n"
43
"attribute vec4 a_position;\n"
44
"uniform mat4 u_viewproj;\n"
45
"void main() {\n"
46
" gl_Position = u_viewproj * a_position;\n"
47
" gl_Position.z = 1.0;\n"
48
"}\n";
49
50
static GLSLProgram *previewProgram = nullptr;
51
static GLSLProgram *texPreviewProgram = nullptr;
52
53
static GLuint previewVao = 0;
54
static GLuint texPreviewVao = 0;
55
static GLuint vbuf = 0;
56
static GLuint ibuf = 0;
57
58
static const GLuint glprim[8] = {
59
GL_POINTS,
60
GL_LINES,
61
GL_LINE_STRIP,
62
GL_TRIANGLES,
63
GL_TRIANGLE_STRIP,
64
GL_TRIANGLE_FAN,
65
// This is for RECTANGLES (see ExpandRectangles().)
66
GL_TRIANGLES,
67
};
68
69
static void BindPreviewProgram(GLSLProgram *&prog) {
70
if (prog == nullptr) {
71
prog = glsl_create_source(preview_vs, preview_fs);
72
}
73
74
glsl_bind(prog);
75
}
76
77
u32 CGEDebugger::PrimPreviewOp() {
78
DisplayList list;
79
if (gpuDebug != nullptr && gpuDebug->GetCurrentDisplayList(list)) {
80
const u32 op = Memory::Read_U32(list.pc);
81
const u32 cmd = op >> 24;
82
if (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE) {
83
return op;
84
}
85
}
86
return 0;
87
}
88
89
void CGEDebugger::UpdatePrimPreview(u32 op, int which) {
90
which &= previewsEnabled_;
91
92
if (which == 0) {
93
return;
94
}
95
96
static std::vector<GPUDebugVertex> vertices;
97
static std::vector<u16> indices;
98
99
int count = 0;
100
GEPrimitiveType prim;
101
if (!GetPrimPreview(op, prim, vertices, indices, count)) {
102
return;
103
}
104
105
float fw, fh;
106
float x, y;
107
108
const float invRealTexWidth = 1.0f / gstate_c.curTextureWidth;
109
const float invRealTexHeight = 1.0f / gstate_c.curTextureHeight;
110
111
// Preview positions on the framebuffer
112
if (which & 1) {
113
primaryWindow->Begin();
114
primaryWindow->GetContentSize(x, y, fw, fh);
115
116
glEnable(GL_BLEND);
117
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
118
glBlendEquation(GL_FUNC_ADD);
119
glBindTexture(GL_TEXTURE_2D, 0);
120
// The surface is upside down, so vertical offsets are negated.
121
glViewport((GLint)x, (GLint)-(y + fh - primaryWindow->Height()), (GLsizei)fw, (GLsizei)fh);
122
glScissor((GLint)x, (GLint)-(y + fh - primaryWindow->Height()), (GLsizei)fw, (GLsizei)fh);
123
BindPreviewProgram(previewProgram);
124
125
if (previewVao == 0 && gl_extensions.ARB_vertex_array_object) {
126
glGenVertexArrays(1, &previewVao);
127
glBindVertexArray(previewVao);
128
glEnableVertexAttribArray(previewProgram->a_position);
129
130
if (ibuf == 0)
131
glGenBuffers(1, &ibuf);
132
if (vbuf == 0)
133
glGenBuffers(1, &vbuf);
134
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuf);
135
glBindBuffer(GL_ARRAY_BUFFER, vbuf);
136
137
glVertexAttribPointer(previewProgram->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (void *)(2 * sizeof(float)));
138
}
139
140
if (vbuf != 0) {
141
glBindBuffer(GL_ARRAY_BUFFER, vbuf);
142
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GPUDebugVertex), vertices.data(), GL_STREAM_DRAW);
143
}
144
145
if (ibuf != 0 && !indices.empty()) {
146
glBindVertexArray(previewVao);
147
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(u16), indices.data(), GL_STREAM_DRAW);
148
}
149
150
float scale[] = {
151
480.0f / (float)PSP_CoreParameter().renderWidth,
152
272.0f / (float)PSP_CoreParameter().renderHeight,
153
};
154
155
Lin::Matrix4x4 ortho;
156
ortho.setOrtho(-(float)gstate_c.curRTOffsetX, (primaryWindow->TexWidth() - (int)gstate_c.curRTOffsetX) * scale[0], primaryWindow->TexHeight() * scale[1], 0, -1, 1);
157
glUniformMatrix4fv(previewProgram->u_viewproj, 1, GL_FALSE, ortho.getReadPtr());
158
if (previewVao != 0) {
159
glBindVertexArray(previewVao);
160
} else {
161
glEnableVertexAttribArray(previewProgram->a_position);
162
glVertexAttribPointer(previewProgram->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (float *)vertices.data() + 2);
163
}
164
165
if (indices.empty()) {
166
glDrawArrays(glprim[prim], 0, count);
167
} else {
168
glDrawElements(glprim[prim], count, GL_UNSIGNED_SHORT, previewVao != 0 ? 0 : indices.data());
169
}
170
171
if (previewVao == 0) {
172
glDisableVertexAttribArray(previewProgram->a_position);
173
}
174
175
primaryWindow->End();
176
}
177
178
// Preview UVs on the texture
179
if (which & 2) {
180
secondWindow->Begin();
181
secondWindow->GetContentSize(x, y, fw, fh);
182
183
glEnable(GL_BLEND);
184
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
185
glBlendEquation(GL_FUNC_ADD);
186
glBindTexture(GL_TEXTURE_2D, 0);
187
// The surface is upside down, so vertical offsets are flipped.
188
glViewport((GLint)x, (GLint)-(y + fh - secondWindow->Height()), (GLsizei)fw, (GLsizei)fh);
189
glScissor((GLint)x, (GLint)-(y + fh - secondWindow->Height()), (GLsizei)fw, (GLsizei)fh);
190
BindPreviewProgram(texPreviewProgram);
191
192
if (texPreviewVao == 0 && vbuf != 0 && ibuf != 0 && gl_extensions.ARB_vertex_array_object) {
193
glGenVertexArrays(1, &texPreviewVao);
194
glBindVertexArray(texPreviewVao);
195
glEnableVertexAttribArray(texPreviewProgram->a_position);
196
197
if (ibuf == 0)
198
glGenBuffers(1, &ibuf);
199
if (vbuf == 0)
200
glGenBuffers(1, &vbuf);
201
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuf);
202
glBindBuffer(GL_ARRAY_BUFFER, vbuf);
203
204
glVertexAttribPointer(texPreviewProgram->a_position, 2, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), 0);
205
}
206
207
// TODO: For some reason we have to re-upload the data?
208
if (vbuf != 0) {
209
glBindBuffer(GL_ARRAY_BUFFER, vbuf);
210
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GPUDebugVertex), vertices.data(), GL_STREAM_DRAW);
211
}
212
213
if (ibuf != 0 && !indices.empty()) {
214
glBindVertexArray(texPreviewVao);
215
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(u16), indices.data(), GL_STREAM_DRAW);
216
}
217
218
Lin::Matrix4x4 ortho;
219
ortho.setOrtho(0.0f - (float)gstate_c.curTextureXOffset * invRealTexWidth, 1.0f - (float)gstate_c.curTextureXOffset * invRealTexWidth, 1.0f - (float)gstate_c.curTextureYOffset * invRealTexHeight, 0.0f - (float)gstate_c.curTextureYOffset * invRealTexHeight, -1.0f, 1.0f);
220
glUniformMatrix4fv(texPreviewProgram->u_viewproj, 1, GL_FALSE, ortho.getReadPtr());
221
if (texPreviewVao != 0) {
222
glBindVertexArray(texPreviewVao);
223
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuf);
224
glBindBuffer(GL_ARRAY_BUFFER, vbuf);
225
glEnableVertexAttribArray(texPreviewProgram->a_position);
226
glVertexAttribPointer(texPreviewProgram->a_position, 2, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), 0);
227
} else {
228
glEnableVertexAttribArray(texPreviewProgram->a_position);
229
glVertexAttribPointer(texPreviewProgram->a_position, 2, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (float *)vertices.data());
230
}
231
232
if (indices.empty()) {
233
glDrawArrays(glprim[prim], 0, count);
234
} else {
235
glDrawElements(glprim[prim], count, GL_UNSIGNED_SHORT, texPreviewVao != 0 ? 0 : indices.data());
236
}
237
238
if (texPreviewVao == 0) {
239
glDisableVertexAttribArray(texPreviewProgram->a_position);
240
}
241
242
secondWindow->End();
243
}
244
}
245
246
void CGEDebugger::CleanupPrimPreview() {
247
if (previewProgram) {
248
glsl_destroy(previewProgram);
249
}
250
if (texPreviewProgram) {
251
glsl_destroy(texPreviewProgram);
252
}
253
}
254
255
void CGEDebugger::HandleRedraw(int which) {
256
if (updating_) {
257
return;
258
}
259
260
u32 op = PrimPreviewOp();
261
if (op && !showClut_) {
262
UpdatePrimPreview(op, which);
263
}
264
}
265
266