mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #4066 from unknownbrackets/debugger
GE debugger - fix some preview issues, softgpu stencil fix
This commit is contained in:
commit
07cf92b3a9
6 changed files with 87 additions and 36 deletions
|
@ -112,7 +112,9 @@ struct GPUDebugBuffer {
|
|||
u32 pixelSize = 2;
|
||||
if (fmt == GPU_DBG_FORMAT_8888 || fmt == GPU_DBG_FORMAT_FLOAT) {
|
||||
pixelSize = 4;
|
||||
};
|
||||
} else if (fmt == GPU_DBG_FORMAT_8BIT) {
|
||||
pixelSize = 1;
|
||||
}
|
||||
|
||||
data_ = new u8[pixelSize * stride * height];
|
||||
}
|
||||
|
|
|
@ -1562,7 +1562,7 @@ bool GLES_GPU::GetCurrentTexture(GPUDebugBuffer &buffer) {
|
|||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
|
||||
|
||||
buffer.Allocate(w, h, GE_FORMAT_8888, false);
|
||||
buffer.Allocate(w, h, GE_FORMAT_8888, gstate_c.flipTexture);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.GetData());
|
||||
|
||||
|
|
|
@ -319,22 +319,33 @@ static inline u8 GetPixelStencil(int x, int y)
|
|||
if (gstate.FrameBufFormat() == GE_FORMAT_565) {
|
||||
// TODO: Should we return 0xFF instead here?
|
||||
return 0;
|
||||
} else if (gstate.FrameBufFormat() != GE_FORMAT_8888) {
|
||||
} else if (gstate.FrameBufFormat() == GE_FORMAT_5551) {
|
||||
return ((fb.Get16(x, y, gstate.FrameBufStride()) & 0x8000) != 0) ? 0xFF : 0;
|
||||
} else if (gstate.FrameBufFormat() != GE_FORMAT_4444) {
|
||||
return fb.Get16(x, y, gstate.FrameBufStride()) >> 12;
|
||||
} else {
|
||||
// TODO: Not the whole value?
|
||||
return ((fb.Get32(x, y, gstate.FrameBufStride()) & 0x80000000) != 0) ? 0xFF : 0;
|
||||
return fb.Get32(x, y, gstate.FrameBufStride()) >> 24;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetPixelStencil(int x, int y, u8 value)
|
||||
{
|
||||
// TODO: This seems like it maybe respects the alpha mask (at least in some scenarios?)
|
||||
|
||||
if (gstate.FrameBufFormat() == GE_FORMAT_565) {
|
||||
// Do nothing
|
||||
} else if (gstate.FrameBufFormat() != GE_FORMAT_8888) {
|
||||
fb.Set16(x, y, gstate.FrameBufStride(), (fb.Get16(x, y, gstate.FrameBufStride()) & ~0x8000) | ((value&0x80)<<8));
|
||||
} else if (gstate.FrameBufFormat() == GE_FORMAT_5551) {
|
||||
u16 pixel = fb.Get16(x, y, gstate.FrameBufStride()) & ~0x8000;
|
||||
pixel |= value != 0 ? 0x8000 : 0;
|
||||
fb.Set16(x, y, gstate.FrameBufStride(), pixel);
|
||||
} else if (gstate.FrameBufFormat() != GE_FORMAT_4444) {
|
||||
u16 pixel = fb.Get16(x, y, gstate.FrameBufStride()) & ~0xF000;
|
||||
pixel |= (u16)value << 12;
|
||||
fb.Set16(x, y, gstate.FrameBufStride(), pixel);
|
||||
} else {
|
||||
fb.Set32(x, y, gstate.FrameBufStride(), (fb.Get32(x, y, gstate.FrameBufStride()) & ~0x80000000) | ((value&0x80)<<24));
|
||||
u32 pixel = fb.Get32(x, y, gstate.FrameBufStride()) & ~0xFF000000;
|
||||
pixel |= (u32)value << 24;
|
||||
fb.Set32(x, y, gstate.FrameBufStride(), pixel);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -948,4 +959,39 @@ void DrawTriangle(const VertexData& v0, const VertexData& v1, const VertexData&
|
|||
}
|
||||
}
|
||||
|
||||
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer)
|
||||
{
|
||||
buffer.Allocate(gstate.DepthBufStride(), 512, GPU_DBG_FORMAT_8BIT);
|
||||
|
||||
u8 *row = buffer.GetData();
|
||||
for (int y = 0; y < 512; ++y) {
|
||||
for (int x = 0; x < gstate.DepthBufStride(); ++x) {
|
||||
row[x] = GetPixelStencil(x, y);
|
||||
}
|
||||
row += gstate.DepthBufStride();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetCurrentTexture(GPUDebugBuffer &buffer)
|
||||
{
|
||||
int w = gstate.getTextureWidth(0);
|
||||
int h = gstate.getTextureHeight(0);
|
||||
buffer.Allocate(w, h, GE_FORMAT_8888, false);
|
||||
|
||||
GETextureFormat texfmt = gstate.getTextureFormat();
|
||||
u32 texaddr = gstate.getTextureAddress(0);
|
||||
int texbufwidthbits = GetTextureBufw(0, texaddr, texfmt) * 8;
|
||||
u8 *texptr = Memory::GetPointer(texaddr);
|
||||
|
||||
u32 *row = (u32 *)buffer.GetData();
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
row[x] = SampleNearest(0, x, y, texptr, texbufwidthbits);
|
||||
}
|
||||
row += w;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -19,9 +19,14 @@
|
|||
|
||||
#include "TransformUnit.h" // for DrawingCoords
|
||||
|
||||
struct GPUDebugBuffer;
|
||||
|
||||
namespace Rasterizer {
|
||||
|
||||
// Draws a triangle if its vertices are specified in counter-clockwise order
|
||||
void DrawTriangle(const VertexData& v0, const VertexData& v1, const VertexData& v2);
|
||||
|
||||
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer);
|
||||
bool GetCurrentTexture(GPUDebugBuffer &buffer);
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "GPU/Software/SoftGpu.h"
|
||||
#include "GPU/Software/TransformUnit.h"
|
||||
#include "GPU/Software/Colors.h"
|
||||
#include "GPU/Software/Rasterizer.h"
|
||||
|
||||
static GLuint temp_texture = 0;
|
||||
|
||||
|
@ -759,32 +760,16 @@ bool SoftGPU::GetCurrentDepthbuffer(GPUDebugBuffer &buffer)
|
|||
{
|
||||
// We don't know the height, so just use 512, which should be the max (hopefully?)
|
||||
// TODO: Could check clipping and such, though...?
|
||||
// TODO: Is the value 16-bit? It seems to be.
|
||||
buffer = GPUDebugBuffer(depthbuf.data, gstate.DepthBufStride(), 512, GPU_DBG_FORMAT_16BIT);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SoftGPU::GetCurrentStencilbuffer(GPUDebugBuffer &buffer)
|
||||
{
|
||||
// TODO: Just need the alpha value from the framebuffer...
|
||||
return false;
|
||||
return Rasterizer::GetCurrentStencilbuffer(buffer);
|
||||
}
|
||||
|
||||
bool SoftGPU::GetCurrentTexture(GPUDebugBuffer &buffer)
|
||||
{
|
||||
static const int level = 0;
|
||||
u32 bufw = GetTextureBufw(level, gstate.getTextureAddress(level), gstate.getTextureFormat());
|
||||
switch (gstate.getTextureFormat())
|
||||
{
|
||||
case GE_TFMT_5650:
|
||||
case GE_TFMT_5551:
|
||||
case GE_TFMT_4444:
|
||||
case GE_TFMT_8888:
|
||||
buffer = GPUDebugBuffer(Memory::GetPointer(gstate.getTextureAddress(level)), bufw, gstate.getTextureHeight(level), gstate.getTextureFormat());
|
||||
return true;
|
||||
|
||||
default:
|
||||
// TODO: Support these...
|
||||
return false;
|
||||
}
|
||||
return Rasterizer::GetCurrentTexture(buffer);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
enum PauseAction {
|
||||
PAUSE_CONTINUE,
|
||||
PAUSE_BREAK,
|
||||
PAUSE_GETFRAMEBUF,
|
||||
PAUSE_GETDEPTHBUF,
|
||||
PAUSE_GETSTENCILBUF,
|
||||
|
@ -52,6 +53,7 @@ static condition_variable pauseWait;
|
|||
static PauseAction pauseAction = PAUSE_CONTINUE;
|
||||
static recursive_mutex actionLock;
|
||||
static condition_variable actionWait;
|
||||
static bool actionComplete;
|
||||
|
||||
static recursive_mutex breaksLock;
|
||||
static std::vector<bool> breakCmds;
|
||||
|
@ -110,15 +112,18 @@ bool CGEDebugger::IsOpOrTextureBreakPoint(u32 op) {
|
|||
return IsOpBreakPoint(op) || IsTextureBreakPoint(op);
|
||||
}
|
||||
|
||||
static void SetPauseAction(PauseAction act) {
|
||||
static void SetPauseAction(PauseAction act, bool waitComplete = true) {
|
||||
{
|
||||
lock_guard guard(pauseLock);
|
||||
actionLock.lock();
|
||||
pauseAction = act;
|
||||
}
|
||||
|
||||
actionComplete = false;
|
||||
pauseWait.notify_one();
|
||||
actionWait.wait(actionLock);
|
||||
while (waitComplete && !actionComplete) {
|
||||
actionWait.wait(actionLock);
|
||||
}
|
||||
actionLock.unlock();
|
||||
}
|
||||
|
||||
|
@ -130,6 +135,9 @@ static void RunPauseAction() {
|
|||
// Don't notify, just go back, woke up by accident.
|
||||
return;
|
||||
|
||||
case PAUSE_BREAK:
|
||||
break;
|
||||
|
||||
case PAUSE_GETFRAMEBUF:
|
||||
bufferResult = gpuDebug->GetCurrentFramebuffer(bufferFrame);
|
||||
break;
|
||||
|
@ -154,15 +162,15 @@ static void RunPauseAction() {
|
|||
ERROR_LOG(HLE, "Unsupported pause action, forgot to add it to the switch.");
|
||||
}
|
||||
|
||||
actionComplete = true;
|
||||
actionWait.notify_one();
|
||||
pauseAction = PAUSE_CONTINUE;
|
||||
pauseAction = PAUSE_BREAK;
|
||||
}
|
||||
|
||||
static void ForceUnpause() {
|
||||
lock_guard guard(pauseLock);
|
||||
lock_guard actionGuard(actionLock);
|
||||
pauseAction = PAUSE_CONTINUE;
|
||||
pauseWait.notify_one();
|
||||
SetPauseAction(PAUSE_CONTINUE, false);
|
||||
actionComplete = true;
|
||||
actionWait.notify_one();
|
||||
}
|
||||
|
||||
CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent)
|
||||
|
@ -408,7 +416,7 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
|||
attached = true;
|
||||
SetupPreviews();
|
||||
|
||||
pauseWait.notify_one();
|
||||
SetPauseAction(PAUSE_CONTINUE, false);
|
||||
breakNextOp = false;
|
||||
breakNextDraw = true;
|
||||
break;
|
||||
|
@ -424,9 +432,9 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
|||
SetDlgItemText(m_hDlg, IDC_GEDBG_TEXADDR, L"");
|
||||
|
||||
// TODO: detach? Should probably have separate UI, or just on activate?
|
||||
SetPauseAction(PAUSE_CONTINUE, false);
|
||||
breakNextOp = false;
|
||||
breakNextDraw = false;
|
||||
pauseWait.notify_one();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -452,7 +460,7 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
|||
attached = true;
|
||||
SetupPreviews();
|
||||
|
||||
pauseWait.notify_one();
|
||||
SetPauseAction(PAUSE_CONTINUE, false);
|
||||
breakNextOp = true;
|
||||
breakNextDraw = false;
|
||||
break;
|
||||
|
@ -503,6 +511,11 @@ static void PauseWithMessage(UINT msg, WPARAM wParam = NULL, LPARAM lParam = NUL
|
|||
|
||||
PostMessage(geDebuggerWindow->GetDlgHandle(), msg, wParam, lParam);
|
||||
|
||||
// Just to be sure.
|
||||
if (pauseAction == PAUSE_CONTINUE) {
|
||||
pauseAction = PAUSE_BREAK;
|
||||
}
|
||||
|
||||
do {
|
||||
RunPauseAction();
|
||||
pauseWait.wait(pauseLock);
|
||||
|
|
Loading…
Add table
Reference in a new issue