mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #4567 from unknownbrackets/debugger
Vertex preview (should work for 2D and 3D now)
This commit is contained in:
commit
221dd153f4
15 changed files with 377 additions and 53 deletions
|
@ -176,6 +176,14 @@ private:
|
|||
bool flipped_;
|
||||
};
|
||||
|
||||
struct GPUDebugVertex {
|
||||
float u;
|
||||
float v;
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
class GPUDebugInterface {
|
||||
public:
|
||||
virtual bool GetCurrentDisplayList(DisplayList &list) = 0;
|
||||
|
@ -198,6 +206,10 @@ public:
|
|||
// Calling from a separate thread (e.g. UI) may fail.
|
||||
virtual void SetCmdValue(u32 op) = 0;
|
||||
|
||||
virtual bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Needs to be called from the GPU thread, so on the same thread as a notification is fine.
|
||||
// Calling from a separate thread (e.g. UI) may fail.
|
||||
virtual bool GetCurrentFramebuffer(GPUDebugBuffer &buffer) {
|
||||
|
|
|
@ -42,7 +42,7 @@ int DecFmtSize(u8 fmt) {
|
|||
}
|
||||
}
|
||||
|
||||
void GetIndexBounds(void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound) {
|
||||
void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound) {
|
||||
// Find index bounds. Could cache this in display lists.
|
||||
// Also, this could be greatly sped up with SSE2/NEON, although rarely a bottleneck.
|
||||
int lowerBound = 0x7FFFFFFF;
|
||||
|
|
|
@ -71,7 +71,7 @@ struct TransformedVertex
|
|||
u8 color1[4]; // prelit
|
||||
};
|
||||
|
||||
void GetIndexBounds(void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound);
|
||||
void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound);
|
||||
|
||||
enum {
|
||||
STAT_VERTSSUBMITTED = 0,
|
||||
|
|
|
@ -1644,3 +1644,7 @@ bool GLES_GPU::GetCurrentTexture(GPUDebugBuffer &buffer) {
|
|||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GLES_GPU::GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices) {
|
||||
return transformDraw_.GetCurrentSimpleVertices(count, vertices, indices);
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ public:
|
|||
bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer);
|
||||
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer);
|
||||
bool GetCurrentTexture(GPUDebugBuffer &buffer);
|
||||
bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices);
|
||||
|
||||
protected:
|
||||
virtual void FastRunLoop(DisplayList &list);
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
#include "GPU/GPUState.h"
|
||||
#include "GPU/ge_constants.h"
|
||||
|
||||
#include "GPU/Common/SplineCommon.h"
|
||||
#include "GPU/GLES/StateMapping.h"
|
||||
#include "GPU/GLES/TextureCache.h"
|
||||
#include "GPU/GLES/TransformPipeline.h"
|
||||
|
@ -842,3 +843,111 @@ bool TransformDrawEngine::TestBoundingBox(void* control_points, int vertexCount,
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Probably move this to common code (with normalization?)
|
||||
|
||||
static inline Vec3f ClipToScreen(const Vec4f& coords)
|
||||
{
|
||||
// TODO: Check for invalid parameters (x2 < x1, etc)
|
||||
float vpx1 = getFloat24(gstate.viewportx1);
|
||||
float vpx2 = getFloat24(gstate.viewportx2);
|
||||
float vpy1 = getFloat24(gstate.viewporty1);
|
||||
float vpy2 = getFloat24(gstate.viewporty2);
|
||||
float vpz1 = getFloat24(gstate.viewportz1);
|
||||
float vpz2 = getFloat24(gstate.viewportz2);
|
||||
|
||||
float retx = coords.x * vpx1 / coords.w + vpx2;
|
||||
float rety = coords.y * vpy1 / coords.w + vpy2;
|
||||
float retz = coords.z * vpz1 / coords.w + vpz2;
|
||||
|
||||
// 16 = 0xFFFF / 4095.9375
|
||||
return Vec3f(retx * 16, rety * 16, retz);
|
||||
}
|
||||
|
||||
static Vec3f ScreenToDrawing(const Vec3f& coords)
|
||||
{
|
||||
Vec3f ret;
|
||||
ret.x = coords.x - gstate.getOffsetX16();
|
||||
ret.y = coords.y - gstate.getOffsetY16();
|
||||
|
||||
// Convert from 16 point to float.
|
||||
ret.x *= 1.0 / 16.0;
|
||||
ret.y *= 1.0 / 16.0;
|
||||
ret.z = coords.z;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// TODO: This probably is not the best interface.
|
||||
bool TransformDrawEngine::GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices) {
|
||||
// This is always for the current vertices.
|
||||
u16 indexLowerBound = 0;
|
||||
u16 indexUpperBound = count - 1;
|
||||
|
||||
if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) {
|
||||
const u8 *inds = Memory::GetPointer(gstate_c.indexAddr);
|
||||
const u16 *inds16 = (const u16 *)inds;
|
||||
|
||||
if (inds) {
|
||||
GetIndexBounds(inds, count, gstate.vertType, &indexLowerBound, &indexUpperBound);
|
||||
indices.resize(count);
|
||||
switch (gstate.vertType & GE_VTYPE_IDX_MASK) {
|
||||
case GE_VTYPE_IDX_16BIT:
|
||||
for (int i = 0; i < count; ++i) {
|
||||
indices[i] = inds16[i];
|
||||
}
|
||||
break;
|
||||
case GE_VTYPE_IDX_8BIT:
|
||||
for (int i = 0; i < count; ++i) {
|
||||
indices[i] = inds[i];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
indices.clear();
|
||||
}
|
||||
} else {
|
||||
indices.clear();
|
||||
}
|
||||
|
||||
// TODO: Manage better.
|
||||
u8 *temp_buffer = new u8[65536 * 24];
|
||||
SimpleVertex *simpleVertices = new SimpleVertex[indexUpperBound + 1];
|
||||
NormalizeVertices((u8 *)simpleVertices, temp_buffer, Memory::GetPointer(gstate_c.vertexAddr), indexLowerBound, indexUpperBound, gstate.vertType);
|
||||
|
||||
vertices.resize(indexUpperBound + 1);
|
||||
for (int i = indexLowerBound; i <= indexUpperBound; ++i) {
|
||||
const SimpleVertex &vert = simpleVertices[i];
|
||||
|
||||
if (gstate.isModeThrough()) {
|
||||
vertices[i].u = vert.uv[0];
|
||||
vertices[i].v = vert.uv[1];
|
||||
vertices[i].x = vert.pos.x;
|
||||
vertices[i].y = vert.pos.y;
|
||||
vertices[i].z = vert.pos.z;
|
||||
} else {
|
||||
// TODO: This doesn't work correctly and is inefficient.
|
||||
|
||||
float worldPos[3];
|
||||
Vec3ByMatrix43(worldPos, vert.pos.AsArray(), gstate.worldMatrix);
|
||||
float viewPos[3];
|
||||
Vec3ByMatrix43(viewPos, worldPos, gstate.viewMatrix);
|
||||
float clipPos[4];
|
||||
Vec3ByMatrix44(clipPos, viewPos, gstate.projMatrix);
|
||||
Vec3f screenPos = ClipToScreen(clipPos);
|
||||
Vec3f drawPos = ScreenToDrawing(screenPos);
|
||||
|
||||
vertices[i].u = vert.uv[0];
|
||||
vertices[i].v = vert.uv[1];
|
||||
vertices[i].x = drawPos.x;
|
||||
vertices[i].y = drawPos.y;
|
||||
vertices[i].z = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
delete [] temp_buffer;
|
||||
delete [] simpleVertices;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <map>
|
||||
|
||||
#include "GPU/Common/GPUDebugInterface.h"
|
||||
#include "GPU/Common/IndexGenerator.h"
|
||||
#include "GPU/GLES/VertexDecoder.h"
|
||||
#include "gfx/gl_common.h"
|
||||
|
@ -97,6 +98,8 @@ public:
|
|||
void SubmitBezier(void* control_points, void* indices, int count_u, int count_v, GEPatchPrimType prim_type, u32 vertType);
|
||||
bool TestBoundingBox(void* control_points, int vertexCount, u32 vertType);
|
||||
|
||||
bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices);
|
||||
|
||||
void SetShaderManager(ShaderManager *shaderManager) {
|
||||
shaderManager_ = shaderManager;
|
||||
}
|
||||
|
|
30
GPU/Math3D.h
30
GPU/Math3D.h
|
@ -40,6 +40,7 @@ public:
|
|||
};
|
||||
|
||||
T* AsArray() { return &x; }
|
||||
const T* AsArray() const { return &x; }
|
||||
|
||||
Vec2() {}
|
||||
Vec2(const T a[2]) : x(a[0]), y(a[1]) {}
|
||||
|
@ -155,12 +156,6 @@ public:
|
|||
Vec2 ts() const { return Vec2(y, x); }
|
||||
};
|
||||
|
||||
template<typename T, typename V>
|
||||
Vec2<T> operator * (const V& f, const Vec2<T>& vec)
|
||||
{
|
||||
return Vec2<T>(f*vec.x,f*vec.y);
|
||||
}
|
||||
|
||||
typedef Vec2<float> Vec2f;
|
||||
|
||||
template<typename T>
|
||||
|
@ -173,6 +168,7 @@ public:
|
|||
};
|
||||
|
||||
T* AsArray() { return &x; }
|
||||
const T* AsArray() const { return &x; }
|
||||
|
||||
Vec3() {}
|
||||
Vec3(const T a[3]) : x(a[0]), y(a[1]), z(a[2]) {}
|
||||
|
@ -321,12 +317,6 @@ public:
|
|||
#undef _DEFINE_SWIZZLER2
|
||||
};
|
||||
|
||||
template<typename T, typename V>
|
||||
Vec3<T> operator * (const V& f, const Vec3<T>& vec)
|
||||
{
|
||||
return Vec3<T>(f*vec.x,f*vec.y,f*vec.z);
|
||||
}
|
||||
|
||||
typedef Vec3<float> Vec3f;
|
||||
|
||||
template<typename T>
|
||||
|
@ -339,6 +329,7 @@ public:
|
|||
};
|
||||
|
||||
T* AsArray() { return &x; }
|
||||
const T* AsArray() const { return &x; }
|
||||
|
||||
Vec4() {}
|
||||
Vec4(const T a[4]) : x(a[0]), y(a[1]), z(a[2]), w(a[3]) {}
|
||||
|
@ -494,12 +485,6 @@ public:
|
|||
#undef _DEFINE_SWIZZLER3
|
||||
};
|
||||
|
||||
template<typename T, typename V>
|
||||
Vec4<T> operator * (const V& f, const Vec4<T>& vec)
|
||||
{
|
||||
return Vec4<T>(f*vec.x,f*vec.y,f*vec.z,f*vec.w);
|
||||
}
|
||||
|
||||
typedef Vec4<float> Vec4f;
|
||||
|
||||
|
||||
|
@ -530,7 +515,7 @@ public:
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
Vec3<T> operator * (const Vec3<T>& vec)
|
||||
Vec3<T> operator * (const Vec3<T>& vec) const
|
||||
{
|
||||
Vec3<T> ret;
|
||||
ret.x = values[0]*vec.x + values[3]*vec.y + values[6]*vec.z;
|
||||
|
@ -539,7 +524,7 @@ public:
|
|||
return ret;
|
||||
}
|
||||
|
||||
Mat3x3 Inverse()
|
||||
Mat3x3 Inverse() const
|
||||
{
|
||||
float a = values[0];
|
||||
float b = values[1];
|
||||
|
@ -555,7 +540,7 @@ public:
|
|||
b*f-c*e, c*d-a*f, a*e-b*d) / Det();
|
||||
}
|
||||
|
||||
BaseType Det()
|
||||
BaseType Det() const
|
||||
{
|
||||
return values[0]*values[4]*values[8] + values[3]*values[7]*values[2] +
|
||||
values[6]*values[1]*values[5] - values[2]*values[4]*values[6] -
|
||||
|
@ -588,7 +573,7 @@ public:
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
Vec4<T> operator * (const Vec4<T>& vec)
|
||||
Vec4<T> operator * (const Vec4<T>& vec) const
|
||||
{
|
||||
Vec4<T> ret;
|
||||
ret.x = values[0]*vec.x + values[4]*vec.y + values[8]*vec.z + values[12]*vec.w;
|
||||
|
@ -615,6 +600,7 @@ inline void Vec3ByMatrix44(float vecOut[4], const float v[3], const float m[16])
|
|||
vecOut[0] = v[0] * m[0] + v[1] * m[4] + v[2] * m[8] + m[12];
|
||||
vecOut[1] = v[0] * m[1] + v[1] * m[5] + v[2] * m[9] + m[13];
|
||||
vecOut[2] = v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + m[14];
|
||||
vecOut[3] = v[0] * m[3] + v[1] * m[7] + v[2] * m[11] + m[15];
|
||||
}
|
||||
|
||||
inline void Vec4ByMatrix44(float vecOut[4], const float v[4], const float m[16])
|
||||
|
|
|
@ -572,7 +572,7 @@ static inline Vec4<int> GetTextureFunctionOutput(const Vec3<int>& prim_color_rgb
|
|||
{
|
||||
int t = (rgba) ? texcolor.a() : 255;
|
||||
int invt = (rgba) ? 255 - t : 0;
|
||||
out_rgb = (invt * prim_color_rgb + t * texcolor.rgb()) / 255;
|
||||
out_rgb = (prim_color_rgb * invt + texcolor.rgb() * t) / 255;
|
||||
out_a = prim_color_a;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -128,9 +128,9 @@ static VertexData ReadVertex(VertexReader& vreader)
|
|||
|
||||
for (int i = 0; i < vertTypeGetNumBoneWeights(gstate.vertType); ++i) {
|
||||
Mat3x3<float> bone(&gstate.boneMatrix[12*i]);
|
||||
tmppos += W[i] * (bone * ModelCoords(pos[0], pos[1], pos[2]) + Vec3<float>(gstate.boneMatrix[12*i+9], gstate.boneMatrix[12*i+10], gstate.boneMatrix[12*i+11]));
|
||||
tmppos += (bone * ModelCoords(pos[0], pos[1], pos[2]) * W[i] + Vec3<float>(gstate.boneMatrix[12*i+9], gstate.boneMatrix[12*i+10], gstate.boneMatrix[12*i+11]));
|
||||
if (vreader.hasNormal())
|
||||
tmpnrm += W[i] * (bone * vertex.normal);
|
||||
tmpnrm += (bone * vertex.normal) * W[i];
|
||||
}
|
||||
|
||||
pos[0] = tmppos.x;
|
||||
|
|
|
@ -116,6 +116,7 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent)
|
|||
}
|
||||
|
||||
CGEDebugger::~CGEDebugger() {
|
||||
CleanupPrimPreview();
|
||||
delete flags;
|
||||
delete lighting;
|
||||
delete textureState;
|
||||
|
|
|
@ -64,6 +64,7 @@ private:
|
|||
void SetupPreviews();
|
||||
void UpdatePreviews();
|
||||
void UpdatePrimPreview(u32 op);
|
||||
void CleanupPrimPreview();
|
||||
void UpdateSize(WORD width, WORD height);
|
||||
void SavePosition();
|
||||
void SetBreakNext(BreakNextType type);
|
||||
|
|
|
@ -261,6 +261,33 @@ void SimpleGLWindow::Draw(u8 *data, int w, int h, bool flipped, Format fmt) {
|
|||
Redraw();
|
||||
}
|
||||
|
||||
void SimpleGLWindow::GetContentSize(float &x, float &y, float &fw, float &fh) {
|
||||
fw = (float)tw_;
|
||||
fh = (float)th_;
|
||||
x = 0.0f;
|
||||
y = 0.0f;
|
||||
|
||||
if (flags_ & (RESIZE_SHRINK_FIT | RESIZE_CENTER) && !zoom_) {
|
||||
float wscale = fw / w_, hscale = fh / h_;
|
||||
|
||||
// Too wide, and width is the biggest problem, so scale based on that.
|
||||
if (wscale > 1.0f && wscale > hscale) {
|
||||
fw = (float)w_;
|
||||
fh /= wscale;
|
||||
} else if (hscale > 1.0f) {
|
||||
fw /= hscale;
|
||||
fh = (float)h_;
|
||||
}
|
||||
}
|
||||
if (flags_ & RESIZE_CENTER) {
|
||||
x = ((float)w_ - fw) / 2;
|
||||
y = ((float)h_ - fh) / 2;
|
||||
}
|
||||
|
||||
x += offsetX_;
|
||||
y += offsetY_;
|
||||
}
|
||||
|
||||
void SimpleGLWindow::Redraw(bool andSwap) {
|
||||
DrawChecker();
|
||||
|
||||
|
@ -284,27 +311,9 @@ void SimpleGLWindow::Redraw(bool andSwap) {
|
|||
glBindTexture(GL_TEXTURE_2D, tex_);
|
||||
glsl_bind(drawProgram_);
|
||||
|
||||
float fw = (float)tw_, fh = (float)th_;
|
||||
float x = 0.0f, y = 0.0f;
|
||||
if (flags_ & (RESIZE_SHRINK_FIT | RESIZE_CENTER) && !zoom_) {
|
||||
float wscale = fw / w_, hscale = fh / h_;
|
||||
|
||||
// Too wide, and width is the biggest problem, so scale based on that.
|
||||
if (wscale > 1.0f && wscale > hscale) {
|
||||
fw = (float)w_;
|
||||
fh /= wscale;
|
||||
} else if (hscale > 1.0f) {
|
||||
fw /= hscale;
|
||||
fh = (float)h_;
|
||||
}
|
||||
}
|
||||
if (flags_ & RESIZE_CENTER) {
|
||||
x = ((float)w_ - fw) / 2;
|
||||
y = ((float)h_ - fh) / 2;
|
||||
}
|
||||
|
||||
x += offsetX_;
|
||||
y += offsetY_;
|
||||
float fw, fh;
|
||||
float x, y;
|
||||
GetContentSize(x, y, fw, fh);
|
||||
|
||||
const float pos[12] = {x,y,0, x+fw,y,0, x+fw,y+fh,0, x,y+fh,0};
|
||||
static const float texCoords[8] = {0,0, 1,0, 1,1, 0,1};
|
||||
|
@ -332,9 +341,15 @@ void SimpleGLWindow::Clear() {
|
|||
|
||||
void SimpleGLWindow::Begin() {
|
||||
Redraw(false);
|
||||
|
||||
glDisableVertexAttribArray(drawProgram_->a_position);
|
||||
glDisableVertexAttribArray(drawProgram_->a_texcoord0);
|
||||
}
|
||||
|
||||
void SimpleGLWindow::End() {
|
||||
glEnableVertexAttribArray(drawProgram_->a_position);
|
||||
glEnableVertexAttribArray(drawProgram_->a_texcoord0);
|
||||
|
||||
Swap();
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,24 @@ struct SimpleGLWindow {
|
|||
SwapBuffers(hDC_);
|
||||
}
|
||||
|
||||
int Width() {
|
||||
return w_;
|
||||
}
|
||||
|
||||
int Height() {
|
||||
return h_;
|
||||
}
|
||||
|
||||
int TexWidth() {
|
||||
return tw_;
|
||||
}
|
||||
|
||||
int TexHeight() {
|
||||
return th_;
|
||||
}
|
||||
|
||||
void GetContentSize(float &x, float &y, float &fw, float &fh);
|
||||
|
||||
static void RegisterClass();
|
||||
protected:
|
||||
void SetupGL();
|
||||
|
|
|
@ -15,17 +15,133 @@
|
|||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "math/lin/matrix4x4.h"
|
||||
#include "gfx_es2/glsl_program.h"
|
||||
#include "Windows/GEDebugger/GEDebugger.h"
|
||||
#include "Windows/GEDebugger/SimpleGLWindow.h"
|
||||
#include "GPU/GPUInterface.h"
|
||||
#include "GPU/Common/GPUDebugInterface.h"
|
||||
#include "GPU/GPUState.h"
|
||||
|
||||
// TODO: Possibly a shader here to do the transforms?
|
||||
static const char preview_fs[] =
|
||||
"#ifdef GL_ES\n"
|
||||
"precision mediump float;\n"
|
||||
"#endif\n"
|
||||
"void main() {\n"
|
||||
" gl_FragColor = vec4(1.0, 0.0, 0.0, 0.6);\n"
|
||||
"}\n";
|
||||
|
||||
static const char preview_vs[] =
|
||||
#ifndef USING_GLES2
|
||||
"#version 120\n"
|
||||
#endif
|
||||
"attribute vec4 a_position;\n"
|
||||
"uniform mat4 u_viewproj;\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = u_viewproj * a_position;\n"
|
||||
"}\n";
|
||||
|
||||
static GLSLProgram *previewProgram = NULL;
|
||||
static GLSLProgram *texPreviewProgram = NULL;
|
||||
|
||||
static const GLuint glprim[8] = {
|
||||
GL_POINTS,
|
||||
GL_LINES,
|
||||
GL_LINE_STRIP,
|
||||
GL_TRIANGLES,
|
||||
GL_TRIANGLE_STRIP,
|
||||
GL_TRIANGLE_FAN,
|
||||
// This is for RECTANGLES (see ExpandRectangles().)
|
||||
GL_TRIANGLES,
|
||||
};
|
||||
|
||||
static void BindPreviewProgram(GLSLProgram *&prog) {
|
||||
if (prog == NULL) {
|
||||
prog = glsl_create_source(preview_vs, preview_fs);
|
||||
}
|
||||
|
||||
glsl_bind(prog);
|
||||
}
|
||||
|
||||
static void SwapUVs(GPUDebugVertex &a, GPUDebugVertex &b) {
|
||||
float tempu = a.u;
|
||||
float tempv = a.v;
|
||||
a.u = b.u;
|
||||
a.v = b.v;
|
||||
b.u = tempu;
|
||||
b.v = tempv;
|
||||
}
|
||||
|
||||
static void RotateUVThrough(GPUDebugVertex v[4]) {
|
||||
float x1 = v[2].x;
|
||||
float x2 = v[0].x;
|
||||
float y1 = v[2].y;
|
||||
float y2 = v[0].y;
|
||||
|
||||
if ((x1 < x2 && y1 > y2) || (x1 > x2 && y1 < y2))
|
||||
SwapUVs(v[1], v[3]);
|
||||
}
|
||||
|
||||
static void ExpandRectangles(std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices, int &count, bool throughMode) {
|
||||
static std::vector<GPUDebugVertex> newVerts;
|
||||
static std::vector<u16> newInds;
|
||||
|
||||
bool useInds = true;
|
||||
size_t numInds = indices.size();
|
||||
if (indices.empty()) {
|
||||
useInds = false;
|
||||
numInds = count;
|
||||
}
|
||||
|
||||
// Will need 4 coords and 6 points per rectangle (currently 2 each.)
|
||||
newVerts.resize(numInds * 2);
|
||||
newInds.resize(numInds * 3);
|
||||
|
||||
u16 v = 0;
|
||||
GPUDebugVertex *vert = &newVerts[0];
|
||||
u16 *ind = &newInds[0];
|
||||
for (size_t i = 0, end = numInds; i < end; i += 2) {
|
||||
const auto &orig_tl = useInds ? vertices[indices[i]] : vertices[i];
|
||||
const auto &orig_br = useInds ? vertices[indices[i + 1]] : vertices[i + 1];
|
||||
|
||||
vert[0] = orig_br;
|
||||
|
||||
// Top right.
|
||||
vert[1] = orig_br;
|
||||
vert[1].y = orig_tl.y;
|
||||
vert[1].v = orig_tl.v;
|
||||
|
||||
vert[2] = orig_tl;
|
||||
|
||||
// Bottom left.
|
||||
vert[3] = orig_br;
|
||||
vert[3].x = orig_tl.x;
|
||||
vert[3].u = orig_tl.u;
|
||||
|
||||
// That's the four corners. Now process UV rotation.
|
||||
if (throughMode)
|
||||
RotateUVThrough(vert);
|
||||
|
||||
// Build the two 3 point triangles from our 4 coordinates.
|
||||
*ind++ = v + 0;
|
||||
*ind++ = v + 1;
|
||||
*ind++ = v + 2;
|
||||
*ind++ = v + 3;
|
||||
*ind++ = v + 0;
|
||||
*ind++ = v + 2;
|
||||
|
||||
vert += 4;
|
||||
v += 4;
|
||||
}
|
||||
|
||||
std::swap(vertices, newVerts);
|
||||
std::swap(indices, newInds);
|
||||
count *= 3;
|
||||
}
|
||||
|
||||
void CGEDebugger::UpdatePrimPreview(u32 op) {
|
||||
const u32 prim_type = (op >> 16) & 0xFF;
|
||||
const u32 count = op & 0xFFFF;
|
||||
int count = op & 0xFFFF;
|
||||
if (prim_type >= 7) {
|
||||
ERROR_LOG(COMMON, "Unsupported prim type: %x", op);
|
||||
return;
|
||||
|
@ -39,12 +155,70 @@ void CGEDebugger::UpdatePrimPreview(u32 op) {
|
|||
}
|
||||
|
||||
const GEPrimitiveType prim = static_cast<GEPrimitiveType>(prim_type);
|
||||
static std::vector<GPUDebugVertex> vertices;
|
||||
static std::vector<u16> indices;
|
||||
|
||||
if (!gpuDebug->GetCurrentSimpleVertices(count, vertices, indices)) {
|
||||
ERROR_LOG(COMMON, "Vertex preview not yet supported");
|
||||
return;
|
||||
}
|
||||
|
||||
if (prim == GE_PRIM_RECTANGLES) {
|
||||
ExpandRectangles(vertices, indices, count, gpuDebug->GetGState().isModeThrough());
|
||||
}
|
||||
|
||||
float fw, fh;
|
||||
float x, y;
|
||||
|
||||
frameWindow->Begin();
|
||||
// TODO: Get the coords, render on top of the texture and framebuffer previews.
|
||||
// TODO: glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);?
|
||||
frameWindow->GetContentSize(x, y, fw, fh);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glViewport(x, y, fw, fh);
|
||||
glScissor(x, y, fw, fh);
|
||||
BindPreviewProgram(previewProgram);
|
||||
|
||||
Matrix4x4 ortho;
|
||||
ortho.setOrtho(0, frameWindow->TexWidth(), frameWindow->TexHeight(), 0, -1, 1);
|
||||
glUniformMatrix4fv(previewProgram->u_viewproj, 1, GL_FALSE, ortho.getReadPtr());
|
||||
glEnableVertexAttribArray(previewProgram->a_position);
|
||||
glVertexAttribPointer(previewProgram->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (float *)vertices.data() + 2);
|
||||
if (indices.empty()) {
|
||||
glDrawArrays(glprim[prim], 0, count);
|
||||
} else {
|
||||
glDrawElements(glprim[prim], count, GL_UNSIGNED_SHORT, indices.data());
|
||||
}
|
||||
|
||||
frameWindow->End();
|
||||
|
||||
texWindow->Begin();
|
||||
texWindow->GetContentSize(x, y, fw, fh);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glViewport(x, y, fw, fh);
|
||||
glScissor(x, y, fw, fh);
|
||||
BindPreviewProgram(texPreviewProgram);
|
||||
|
||||
ortho.setOrtho(0.0, 1.0, 1.0, 0.0, -1.0, 1.0);
|
||||
glUniformMatrix4fv(texPreviewProgram->u_viewproj, 1, GL_FALSE, ortho.getReadPtr());
|
||||
glEnableVertexAttribArray(texPreviewProgram->a_position);
|
||||
glVertexAttribPointer(texPreviewProgram->a_position, 2, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (float *)vertices.data());
|
||||
if (indices.empty()) {
|
||||
glDrawArrays(glprim[prim], 0, count);
|
||||
} else {
|
||||
glDrawElements(glprim[prim], count, GL_UNSIGNED_SHORT, indices.data());
|
||||
}
|
||||
|
||||
texWindow->End();
|
||||
}
|
||||
}
|
||||
|
||||
void CGEDebugger::CleanupPrimPreview() {
|
||||
glsl_destroy(previewProgram);
|
||||
glsl_destroy(texPreviewProgram);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue