mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 13:30:02 +00:00
Merge pull request #4052 from unknownbrackets/debugger
GE debugger - fix depth/stencil, pan/zoom the texture
This commit is contained in:
commit
5dc2cc23b1
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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_;
|
||||
};
|
Loading…
Reference in New Issue
Block a user