Merge pull request #4052 from unknownbrackets/debugger

GE debugger - fix depth/stencil, pan/zoom the texture
This commit is contained in:
Henrik Rydgård 2013-10-05 23:02:44 -07:00
commit 5dc2cc23b1
6 changed files with 165 additions and 38 deletions

View File

@ -1383,7 +1383,7 @@ void FramebufferManager::UpdateFromMemory(u32 addr, int size) {
if (useBufferedRendering_ && vfb->fbo) {
fbo_bind_as_render_target(vfb->fbo);
needUnbind = true;
DrawPixels(Memory::GetPointer(addr), vfb->format, vfb->fb_stride);
DrawPixels(Memory::GetPointer(addr | 0x04000000), vfb->format, vfb->fb_stride);
} else {
INFO_LOG(SCEGE, "Invalidating FBO for %08x (%i x %i x %i)", vfb->fb_address, vfb->width, vfb->height, vfb->format)
DestroyFramebuf(vfb);
@ -1412,13 +1412,16 @@ bool FramebufferManager::GetCurrentFramebuffer(GPUDebugBuffer &buffer) {
if (!vfb) {
// If there's no vfb and we're drawing there, must be memory?
buffer = GPUDebugBuffer(Memory::GetPointer(fb_address), fb_stride, 512, gstate.FrameBufFormat());
buffer = GPUDebugBuffer(Memory::GetPointer(fb_address | 0x04000000), fb_stride, 512, gstate.FrameBufFormat());
return true;
}
buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GE_FORMAT_8888, true);
if (vfb->fbo)
fbo_bind_for_read(vfb->fbo);
#ifndef USING_GLES2
glReadBuffer(GL_COLOR_ATTACHMENT0);
#endif
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glReadPixels(0, 0, vfb->renderWidth, vfb->renderHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer.GetData());
@ -1440,16 +1443,17 @@ bool FramebufferManager::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) {
if (!vfb) {
// If there's no vfb and we're drawing there, must be memory?
// TODO: Is the value 16-bit? It seems to be.
buffer = GPUDebugBuffer(Memory::GetPointer(z_address), z_stride, 512, GPU_DBG_FORMAT_16BIT);
buffer = GPUDebugBuffer(Memory::GetPointer(z_address | 0x04000000), z_stride, 512, GPU_DBG_FORMAT_16BIT);
return true;
}
#ifndef USING_GLES2
buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GPU_DBG_FORMAT_FLOAT, true);
buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GPU_DBG_FORMAT_16BIT, true);
if (vfb->fbo)
fbo_bind_for_read(vfb->fbo);
glReadBuffer(GL_DEPTH_ATTACHMENT);
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glReadPixels(0, 0, vfb->renderWidth, vfb->renderHeight, GL_DEPTH_COMPONENT, GL_FLOAT, buffer.GetData());
glReadPixels(0, 0, vfb->renderWidth, vfb->renderHeight, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, buffer.GetData());
return true;
#else
@ -1468,7 +1472,8 @@ bool FramebufferManager::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) {
if (!vfb) {
// If there's no vfb and we're drawing there, must be memory?
buffer = GPUDebugBuffer(Memory::GetPointer(fb_address), fb_stride, 512, GPU_DBG_FORMAT_8888);
// TODO: Actually get the stencil.
buffer = GPUDebugBuffer(Memory::GetPointer(fb_address | 0x04000000), fb_stride, 512, GPU_DBG_FORMAT_8888);
return true;
}
@ -1476,8 +1481,9 @@ bool FramebufferManager::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) {
buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GPU_DBG_FORMAT_16BIT, true);
if (vfb->fbo)
fbo_bind_for_read(vfb->fbo);
glReadBuffer(GL_STENCIL_ATTACHMENT);
glPixelStorei(GL_PACK_ALIGNMENT, 2);
glReadPixels(0, 0, vfb->renderWidth, vfb->renderHeight, GL_STENCIL_INDEX, GL_UNSIGNED_SHORT, buffer.GetData());
glReadPixels(0, 0, vfb->renderWidth, vfb->renderHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, buffer.GetData());
return true;
#else

View File

@ -283,6 +283,9 @@ void TransformDrawEngine::ApplyDrawState(int prim) {
if (alphaMask && enableStencilTest) {
glstate.stencilTest.enable();
glstate.stencilOp.set(GL_REPLACE, GL_REPLACE, GL_REPLACE);
// TODO: In clear mode, the stencil value is set to the alpha value of the vertex.
// A normal clear will be 2 points, the second point has the color.
// We should set "ref" to that value instead of 0.
glstate.stencilFunc.set(GL_ALWAYS, 0, 0xFF);
} else
glstate.stencilTest.disable();

View File

@ -38,6 +38,8 @@
enum PauseAction {
PAUSE_CONTINUE,
PAUSE_GETFRAMEBUF,
PAUSE_GETDEPTHBUF,
PAUSE_GETSTENCILBUF,
PAUSE_GETTEX,
};
@ -60,6 +62,8 @@ static bool breakNextDraw = false;
static bool bufferResult;
static GPUDebugBuffer bufferFrame;
static GPUDebugBuffer bufferDepth;
static GPUDebugBuffer bufferStencil;
static GPUDebugBuffer bufferTex;
// TODO: Simplify and move out of windows stuff, just block in a common way for everyone.
@ -122,6 +126,14 @@ static void RunPauseAction() {
bufferResult = gpuDebug->GetCurrentFramebuffer(bufferFrame);
break;
case PAUSE_GETDEPTHBUF:
bufferResult = gpuDebug->GetCurrentDepthbuffer(bufferDepth);
break;
case PAUSE_GETSTENCILBUF:
bufferResult = gpuDebug->GetCurrentStencilbuffer(bufferStencil);
break;
case PAUSE_GETTEX:
bufferResult = gpuDebug->GetCurrentTexture(bufferTex);
break;
@ -139,7 +151,7 @@ static void ForceUnpause() {
}
CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent)
: Dialog((LPCSTR)IDD_GEDEBUGGER, _hInstance, _hParent), frameWindow(NULL), texWindow(NULL) {
: Dialog((LPCSTR)IDD_GEDEBUGGER, _hInstance, _hParent), primaryDisplay(PRIMARY_FRAMEBUF), frameWindow(NULL), texWindow(NULL) {
breakCmds.resize(256, false);
Core_ListenShutdown(ForceUnpause);
@ -218,14 +230,30 @@ void CGEDebugger::SetupPreviews() {
void CGEDebugger::UpdatePreviews() {
// TODO: Do something different if not paused?
GPUDebugBuffer *primaryBuffer = NULL;
bufferResult = false;
SetPauseAction(PAUSE_GETFRAMEBUF);
switch (primaryDisplay) {
case PRIMARY_FRAMEBUF:
SetPauseAction(PAUSE_GETFRAMEBUF);
primaryBuffer = &bufferFrame;
break;
if (bufferResult) {
auto fmt = SimpleGLWindow::Format(bufferFrame.GetFormat());
frameWindow->Draw(bufferFrame.GetData(), bufferFrame.GetStride(), bufferFrame.GetHeight(), bufferFrame.GetFlipped(), fmt);
case PRIMARY_DEPTHBUF:
SetPauseAction(PAUSE_GETDEPTHBUF);
primaryBuffer = &bufferDepth;
break;
case PRIMARY_STENCILBUF:
SetPauseAction(PAUSE_GETSTENCILBUF);
primaryBuffer = &bufferStencil;
break;
}
if (bufferResult && primaryBuffer != NULL) {
auto fmt = SimpleGLWindow::Format(primaryBuffer->GetFormat());
frameWindow->Draw(primaryBuffer->GetData(), primaryBuffer->GetStride(), primaryBuffer->GetHeight(), primaryBuffer->GetFlipped(), fmt);
} else {
ERROR_LOG(COMMON, "Unable to get framebuffer.");
ERROR_LOG(COMMON, "Unable to get buffer for main display.");
frameWindow->Clear();
}
@ -235,8 +263,17 @@ void CGEDebugger::UpdatePreviews() {
if (bufferResult) {
auto fmt = SimpleGLWindow::Format(bufferTex.GetFormat());
texWindow->Draw(bufferTex.GetData(), bufferTex.GetStride(), bufferTex.GetHeight(), bufferTex.GetFlipped(), fmt);
if (gpuDebug != NULL) {
auto state = gpuDebug->GetGState();
if (state.isTextureAlphaUsed()) {
texWindow->SetFlags(SimpleGLWindow::ALPHA_BLEND | SimpleGLWindow::RESIZE_SHRINK_CENTER);
} else {
texWindow->SetFlags(SimpleGLWindow::RESIZE_SHRINK_CENTER);
}
}
} else {
ERROR_LOG(COMMON, "Unable to get texture.");
ERROR_LOG(COMMON, "Unable to get texture (may be no texture set.)");
texWindow->Clear();
}

View File

@ -61,6 +61,13 @@ private:
void UpdateSize(WORD width, WORD height);
void SavePosition();
enum PrimaryDisplayType {
PRIMARY_FRAMEBUF,
PRIMARY_DEPTHBUF,
PRIMARY_STENCILBUF,
};
PrimaryDisplayType primaryDisplay;
CtrlDisplayListView *displayList;
TabDisplayLists *lists;
TabStateFlags *flags;

View File

@ -15,6 +15,7 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <WindowsX.h>
#include "math/lin/matrix4x4.h"
#include "gfx_es2/glsl_program.h"
#include "Common/Common.h"
@ -29,13 +30,13 @@ void SimpleGLWindow::RegisterClass() {
wndClass.lpszClassName = windowClass;
wndClass.hInstance = GetModuleHandle(0);
wndClass.lpfnWndProc = WndProc;
wndClass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hIcon = 0;
wndClass.lpszMenuName = 0;
wndClass.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
wndClass.style = 0;
wndClass.style = CS_DBLCLKS;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = sizeof(SimpleGLWindow*);
wndClass.cbWndExtra = sizeof(SimpleGLWindow *);
wndClass.hIconSm = 0;
RegisterClassEx(&wndClass);
@ -66,7 +67,8 @@ static const char basic_vs[] =
"}\n";
SimpleGLWindow::SimpleGLWindow(HWND wnd)
: hWnd_(wnd), valid_(false), drawProgram_(NULL), tex_(0), flags_(0) {
: hWnd_(wnd), valid_(false), drawProgram_(NULL), tex_(0), flags_(0), zoom_(false),
dragging_(false), offsetX_(0), offsetY_(0) {
SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG) this);
}
@ -203,17 +205,7 @@ void SimpleGLWindow::DrawChecker() {
}
void SimpleGLWindow::Draw(u8 *data, int w, int h, bool flipped, Format fmt) {
DrawChecker();
if (flags_ & ALPHA_BLEND) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_ADD);
} else {
glDisable(GL_BLEND);
}
glViewport(0, 0, w_, h_);
glScissor(0, 0, w_, h_);
wglMakeCurrent(hDC_, hGLRC_);
GLint components = GL_RGBA;
GLenum glfmt;
@ -247,11 +239,37 @@ void SimpleGLWindow::Draw(u8 *data, int w, int h, bool flipped, Format fmt) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Reset offset when the texture size changes.
if (tw_ != w || th_ != h) {
tw_ = w;
th_ = h;
offsetX_ = 0;
offsetY_ = 0;
}
tflipped_ = flipped;
Redraw();
}
void SimpleGLWindow::Redraw() {
DrawChecker();
if (flags_ & ALPHA_BLEND) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_ADD);
} else {
glDisable(GL_BLEND);
}
glViewport(0, 0, w_, h_);
glScissor(0, 0, w_, h_);
glBindTexture(GL_TEXTURE_2D, tex_);
glsl_bind(drawProgram_);
float fw = (float)w, fh = (float)h;
float fw = (float)tw_, fh = (float)th_;
float x = 0.0f, y = 0.0f;
if (flags_ & (RESIZE_SHRINK_FIT | RESIZE_SHRINK_CENTER)) {
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.
@ -262,12 +280,15 @@ void SimpleGLWindow::Draw(u8 *data, int w, int h, bool flipped, Format fmt) {
fw /= hscale;
fh = (float)h_;
}
if (flags_ & RESIZE_SHRINK_CENTER) {
x = ((float)w_ - fw) / 2;
y = ((float)h_ - fh) / 2;
}
}
if (flags_ & RESIZE_CENTER) {
x = ((float)w_ - fw) / 2;
y = ((float)h_ - fh) / 2;
}
x += offsetX_;
y += offsetY_;
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};
static const float texCoordsFlipped[8] = {0,1, 1,1, 1,0, 0,0};
@ -277,7 +298,7 @@ void SimpleGLWindow::Draw(u8 *data, int w, int h, bool flipped, Format fmt) {
ortho.setOrtho(0, (float)w_, (float)h_, 0, -1, 1);
glUniformMatrix4fv(drawProgram_->u_viewproj, 1, GL_FALSE, ortho.getReadPtr());
glVertexAttribPointer(drawProgram_->a_position, 3, GL_FLOAT, GL_FALSE, 12, pos);
glVertexAttribPointer(drawProgram_->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, flipped ? texCoordsFlipped : texCoords);
glVertexAttribPointer(drawProgram_->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, tflipped_ ? texCoordsFlipped : texCoords);
glActiveTexture(GL_TEXTURE0);
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, indices);
@ -304,6 +325,43 @@ LRESULT CALLBACK SimpleGLWindow::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPA
// Continue with window creation.
return win != NULL;
case WM_LBUTTONDBLCLK:
win->zoom_ = !win->zoom_;
// Reset the offset when zooming out (or in, doesn't matter.)
win->offsetX_ = 0;
win->offsetY_ = 0;
// Redrawn in WM_LBUTTONUP.
return 0;
case WM_LBUTTONDOWN:
// Only while zoomed in, otherwise it's shrink to fit mode or fixed.
if (win->zoom_) {
win->dragging_ = true;
win->dragStartX_ = GET_X_LPARAM(lParam) - win->offsetX_;
win->dragStartY_ = GET_Y_LPARAM(lParam) - win->offsetY_;
win->dragLastUpdate_ = GetTickCount();
}
return 0;
case WM_LBUTTONUP:
win->dragging_ = false;
win->Redraw();
return 0;
case WM_MOUSEMOVE:
if (win->dragging_) {
int x = GET_X_LPARAM(lParam);
int y = GET_Y_LPARAM(lParam);
win->offsetX_ = x - win->dragStartX_;
win->offsetY_ = y - win->dragStartY_;
const u32 MS_BETWEEN_DRAG_REDRAWS = 5;
if (GetTickCount() - win->dragLastUpdate_ > MS_BETWEEN_DRAG_REDRAWS) {
win->Redraw();
}
return 0;
}
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);

View File

@ -36,8 +36,9 @@ struct SimpleGLWindow {
enum Flags {
RESIZE_NONE = 0x00,
RESIZE_CENTER = 0x02,
RESIZE_SHRINK_FIT = 0x01,
RESIZE_SHRINK_CENTER = 0x02,
RESIZE_SHRINK_CENTER = 0x03,
ALPHA_IGNORE = 0x00,
ALPHA_BLEND = 0x04,
};
@ -47,6 +48,7 @@ struct SimpleGLWindow {
void Clear();
void Draw(u8 *data, int w, int h, bool flipped = false, Format = FORMAT_8888);
void Redraw();
void Initialize(u32 flags);
static SimpleGLWindow *GetFrom(HWND hwnd);
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
@ -71,11 +73,25 @@ protected:
HDC hDC_;
HGLRC hGLRC_;
bool valid_;
// Width and height of the window.
int w_;
int h_;
// Last texture size/flipped for Redraw().
int tw_;
int th_;
bool tflipped_;
GLSLProgram *drawProgram_;
GLuint checker_;
GLuint tex_;
u32 flags_;
// Disable shrink (toggled by double click.)
bool zoom_;
bool dragging_;
int dragStartX_;
int dragStartY_;
u32 dragLastUpdate_;
// Offset to position the texture is drawn at.
int offsetX_;
int offsetY_;
};