mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-24 00:29:57 +00:00
Track hovering in GE debugger to show pixel value.
This works for texture, framebuffer, depth, and stencil. Importantly, allows debugging the actual depth values present.
This commit is contained in:
parent
14fd3136b1
commit
ba15718db3
@ -1455,6 +1455,7 @@ add_library(GPU OBJECT
|
||||
GPU/Common/DepalettizeShaderCommon.h
|
||||
GPU/Common/FramebufferCommon.cpp
|
||||
GPU/Common/FramebufferCommon.h
|
||||
GPU/Common/GPUDebugInterface.cpp
|
||||
GPU/Common/GPUDebugInterface.h
|
||||
GPU/Common/DrawEngineCommon.cpp
|
||||
GPU/Common/DrawEngineCommon.h
|
||||
|
98
GPU/Common/GPUDebugInterface.cpp
Normal file
98
GPU/Common/GPUDebugInterface.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright (c) 2012- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "GPUDebugInterface.h"
|
||||
|
||||
void GPUDebugBuffer::Allocate(u32 stride, u32 height, GEBufferFormat fmt, bool flipped, bool reversed) {
|
||||
GPUDebugBufferFormat actualFmt = GPUDebugBufferFormat(fmt);
|
||||
if (reversed && actualFmt < GPU_DBG_FORMAT_8888) {
|
||||
actualFmt |= GPU_DBG_FORMAT_REVERSE_FLAG;
|
||||
}
|
||||
Allocate(stride, height, actualFmt, flipped);
|
||||
}
|
||||
|
||||
void GPUDebugBuffer::Allocate(u32 stride, u32 height, GPUDebugBufferFormat fmt, bool flipped) {
|
||||
if (alloc_ && stride_ == stride && height_ == height && fmt_ == fmt) {
|
||||
// Already allocated the right size.
|
||||
flipped_ = flipped;
|
||||
return;
|
||||
}
|
||||
|
||||
Free();
|
||||
alloc_ = true;
|
||||
height_ = height;
|
||||
stride_ = stride;
|
||||
fmt_ = fmt;
|
||||
flipped_ = flipped;
|
||||
|
||||
u32 pixelSize = PixelSize(fmt);
|
||||
data_ = new u8[pixelSize * stride * height];
|
||||
}
|
||||
|
||||
void GPUDebugBuffer::Free() {
|
||||
if (alloc_ && data_ != NULL) {
|
||||
delete [] data_;
|
||||
}
|
||||
data_ = NULL;
|
||||
}
|
||||
|
||||
u32 GPUDebugBuffer::PixelSize(GPUDebugBufferFormat fmt) const {
|
||||
switch (fmt) {
|
||||
case GPU_DBG_FORMAT_8888:
|
||||
case GPU_DBG_FORMAT_8888_BGRA:
|
||||
case GPU_DBG_FORMAT_FLOAT:
|
||||
case GPU_DBG_FORMAT_24BIT_8X:
|
||||
case GPU_DBG_FORMAT_24X_8BIT:
|
||||
return 4;
|
||||
|
||||
case GPU_DBG_FORMAT_888_RGB:
|
||||
return 3;
|
||||
|
||||
case GPU_DBG_FORMAT_8BIT:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
u32 GPUDebugBuffer::GetRawPixel(int x, int y) const {
|
||||
if (data_ == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (flipped_) {
|
||||
y = height_ - y - 1;
|
||||
}
|
||||
|
||||
u32 pixelSize = PixelSize(fmt_);
|
||||
u32 byteOffset = pixelSize * (stride_ * y + x);
|
||||
const u8 *ptr = &data_[byteOffset];
|
||||
|
||||
switch (pixelSize) {
|
||||
case 4:
|
||||
return *(const u32 *)ptr;
|
||||
case 3:
|
||||
return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16);
|
||||
case 2:
|
||||
return *(const u16 *)ptr;
|
||||
case 1:
|
||||
return *(const u8 *)ptr;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -121,65 +121,16 @@ struct GPUDebugBuffer {
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Allocate(u32 stride, u32 height, GEBufferFormat fmt, bool flipped = false, bool reversed = false) {
|
||||
GPUDebugBufferFormat actualFmt = GPUDebugBufferFormat(fmt);
|
||||
if (reversed && actualFmt < GPU_DBG_FORMAT_8888) {
|
||||
actualFmt |= GPU_DBG_FORMAT_REVERSE_FLAG;
|
||||
}
|
||||
Allocate(stride, height, actualFmt, flipped);
|
||||
}
|
||||
|
||||
void Allocate(u32 stride, u32 height, GPUDebugBufferFormat fmt, bool flipped = false) {
|
||||
if (alloc_ && stride_ == stride && height_ == height && fmt_ == fmt) {
|
||||
// Already allocated the right size.
|
||||
flipped_ = flipped;
|
||||
return;
|
||||
}
|
||||
|
||||
Free();
|
||||
alloc_ = true;
|
||||
height_ = height;
|
||||
stride_ = stride;
|
||||
fmt_ = fmt;
|
||||
flipped_ = flipped;
|
||||
|
||||
u32 pixelSize;
|
||||
switch (fmt) {
|
||||
case GPU_DBG_FORMAT_8888:
|
||||
case GPU_DBG_FORMAT_8888_BGRA:
|
||||
case GPU_DBG_FORMAT_FLOAT:
|
||||
case GPU_DBG_FORMAT_24BIT_8X:
|
||||
case GPU_DBG_FORMAT_24X_8BIT:
|
||||
pixelSize = 4;
|
||||
break;
|
||||
|
||||
case GPU_DBG_FORMAT_888_RGB:
|
||||
pixelSize = 3;
|
||||
break;
|
||||
|
||||
case GPU_DBG_FORMAT_8BIT:
|
||||
pixelSize = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
pixelSize = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
data_ = new u8[pixelSize * stride * height];
|
||||
}
|
||||
|
||||
void Free() {
|
||||
if (alloc_ && data_ != NULL) {
|
||||
delete [] data_;
|
||||
}
|
||||
data_ = NULL;
|
||||
}
|
||||
void Allocate(u32 stride, u32 height, GEBufferFormat fmt, bool flipped = false, bool reversed = false);
|
||||
void Allocate(u32 stride, u32 height, GPUDebugBufferFormat fmt, bool flipped = false);
|
||||
void Free();
|
||||
|
||||
u8 *GetData() {
|
||||
return data_;
|
||||
}
|
||||
|
||||
u32 GetRawPixel(int x, int y) const;
|
||||
|
||||
const u8 *GetData() const {
|
||||
return data_;
|
||||
}
|
||||
@ -201,6 +152,8 @@ struct GPUDebugBuffer {
|
||||
}
|
||||
|
||||
private:
|
||||
u32 PixelSize(GPUDebugBufferFormat fmt) const;
|
||||
|
||||
bool alloc_;
|
||||
u8 *data_;
|
||||
u32 stride_;
|
||||
|
@ -245,6 +245,7 @@
|
||||
<ClCompile Include="Common\DepalettizeShaderCommon.cpp" />
|
||||
<ClCompile Include="Common\DrawEngineCommon.cpp" />
|
||||
<ClCompile Include="Common\FramebufferCommon.cpp" />
|
||||
<ClCompile Include="Common\GPUDebugInterface.cpp" />
|
||||
<ClCompile Include="Common\IndexGenerator.cpp" />
|
||||
<ClCompile Include="Common\PostShader.cpp" />
|
||||
<ClCompile Include="Common\SplineCommon.cpp" />
|
||||
@ -318,9 +319,6 @@
|
||||
<Project>{3fcdbae2-5103-4350-9a8e-848ce9c73195}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
@ -183,7 +183,9 @@
|
||||
<ClInclude Include="Common\TextureScalerCommon.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GPU.h" />
|
||||
<ClInclude Include="GPU.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Math3D.cpp">
|
||||
@ -351,9 +353,11 @@
|
||||
<ClCompile Include="Common\TextureScalerCommon.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GPU.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
<ClCompile Include="Common\GPUDebugInterface.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GPU.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -42,6 +42,7 @@ SOURCES += $$P/GPU/GeDisasm.cpp \ # GPU
|
||||
$$P/GPU/Software/*.cpp \
|
||||
$$P/GPU/Debugger/*.cpp \
|
||||
$$P/GPU/Common/DepalettizeShaderCommon.cpp \
|
||||
$$P/GPU/Common/GPUDebugInterface.cpp \
|
||||
$$P/GPU/Common/IndexGenerator.cpp \
|
||||
$$P/GPU/Common/TextureDecoder.cpp \
|
||||
$$P/GPU/Common/TextureScalerCommon.cpp \
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <set>
|
||||
|
||||
#include "base/functional.h"
|
||||
#include "Common/ColorConv.h"
|
||||
#include "Windows/GEDebugger/GEDebugger.h"
|
||||
#include "Windows/GEDebugger/SimpleGLWindow.h"
|
||||
#include "Windows/GEDebugger/CtrlDisplayListView.h"
|
||||
@ -58,7 +59,8 @@ void CGEDebugger::Init() {
|
||||
}
|
||||
|
||||
CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent)
|
||||
: Dialog((LPCSTR)IDD_GEDEBUGGER, _hInstance, _hParent), frameWindow(NULL), texWindow(NULL), textureLevel_(0) {
|
||||
: Dialog((LPCSTR)IDD_GEDEBUGGER, _hInstance, _hParent), frameWindow(nullptr), texWindow(nullptr),
|
||||
textureLevel_(0), primaryBuffer_(nullptr), texBuffer_(nullptr) {
|
||||
GPUBreakpoints::Init();
|
||||
Core_ListenShutdown(ForceUnpause);
|
||||
|
||||
@ -137,18 +139,46 @@ CGEDebugger::~CGEDebugger() {
|
||||
}
|
||||
|
||||
void CGEDebugger::SetupPreviews() {
|
||||
if (frameWindow == NULL) {
|
||||
if (frameWindow == nullptr) {
|
||||
frameWindow = SimpleGLWindow::GetFrom(GetDlgItem(m_hDlg, IDC_GEDBG_FRAME));
|
||||
frameWindow->Initialize(SimpleGLWindow::ALPHA_IGNORE | SimpleGLWindow::RESIZE_SHRINK_CENTER);
|
||||
frameWindow->SetHoverCallback([&] (int x, int y) {
|
||||
PreviewFramebufHover(x, y);
|
||||
});
|
||||
frameWindow->Clear();
|
||||
}
|
||||
if (texWindow == NULL) {
|
||||
if (texWindow == nullptr) {
|
||||
texWindow = SimpleGLWindow::GetFrom(GetDlgItem(m_hDlg, IDC_GEDBG_TEX));
|
||||
texWindow->Initialize(SimpleGLWindow::ALPHA_BLEND | SimpleGLWindow::RESIZE_SHRINK_CENTER);
|
||||
texWindow->SetHoverCallback([&] (int x, int y) {
|
||||
PreviewTextureHover(x, y);
|
||||
});
|
||||
texWindow->Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void CGEDebugger::DescribeFramebufTab(const GPUgstate &state, wchar_t desc[256]) {
|
||||
_assert_msg_(MASTER_LOG, primaryBuffer_ != nullptr, "Must have a valid primaryBuffer_");
|
||||
|
||||
switch (PrimaryDisplayType(fbTabs->CurrentTabIndex())) {
|
||||
case PRIMARY_FRAMEBUF:
|
||||
_snwprintf(desc, 256, L"Color: 0x%08x (%dx%d) fmt %i", state.getFrameBufRawAddress(), primaryBuffer_->GetStride(), primaryBuffer_->GetHeight(), state.FrameBufFormat());
|
||||
break;
|
||||
|
||||
case PRIMARY_DEPTHBUF:
|
||||
_snwprintf(desc, 256, L"Depth: 0x%08x (%dx%d)", state.getDepthBufRawAddress(), primaryBuffer_->GetStride(), primaryBuffer_->GetHeight());
|
||||
break;
|
||||
|
||||
case PRIMARY_STENCILBUF:
|
||||
_snwprintf(desc, 256, L"Stencil: 0x%08x (%dx%d)", state.getFrameBufRawAddress(), primaryBuffer_->GetStride(), primaryBuffer_->GetHeight());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CGEDebugger::DescribeTexture(const GPUgstate &state, wchar_t desc[256]) {
|
||||
_snwprintf(desc, 256, L"Texture L%d: 0x%08x (%dx%d)", textureLevel_, state.getTextureAddress(textureLevel_), state.getTextureWidth(textureLevel_), state.getTextureHeight(textureLevel_));
|
||||
}
|
||||
|
||||
void CGEDebugger::UpdatePreviews() {
|
||||
auto memLock = Memory::Lock();
|
||||
if (!PSP_IsInited()) {
|
||||
@ -156,7 +186,6 @@ void CGEDebugger::UpdatePreviews() {
|
||||
}
|
||||
|
||||
wchar_t desc[256];
|
||||
const GPUDebugBuffer *primaryBuffer = NULL;
|
||||
bool bufferResult = false;
|
||||
GPUgstate state = {0};
|
||||
|
||||
@ -164,45 +193,41 @@ void CGEDebugger::UpdatePreviews() {
|
||||
state = gpuDebug->GetGState();
|
||||
}
|
||||
|
||||
primaryBuffer_ = nullptr;
|
||||
switch (PrimaryDisplayType(fbTabs->CurrentTabIndex())) {
|
||||
case PRIMARY_FRAMEBUF:
|
||||
bufferResult = GPU_GetCurrentFramebuffer(primaryBuffer);
|
||||
if (bufferResult) {
|
||||
_snwprintf(desc, ARRAY_SIZE(desc), L"Color: 0x%08x (%dx%d) fmt %i", state.getFrameBufRawAddress(), primaryBuffer->GetStride(), primaryBuffer->GetHeight(), state.FrameBufFormat());
|
||||
}
|
||||
bufferResult = GPU_GetCurrentFramebuffer(primaryBuffer_);
|
||||
break;
|
||||
|
||||
case PRIMARY_DEPTHBUF:
|
||||
bufferResult = GPU_GetCurrentDepthbuffer(primaryBuffer);
|
||||
if (bufferResult) {
|
||||
_snwprintf(desc, ARRAY_SIZE(desc), L"Depth: 0x%08x (%dx%d)", state.getDepthBufRawAddress(), primaryBuffer->GetStride(), primaryBuffer->GetHeight());
|
||||
}
|
||||
bufferResult = GPU_GetCurrentDepthbuffer(primaryBuffer_);
|
||||
break;
|
||||
|
||||
case PRIMARY_STENCILBUF:
|
||||
bufferResult = GPU_GetCurrentStencilbuffer(primaryBuffer);
|
||||
if (bufferResult) {
|
||||
_snwprintf(desc, ARRAY_SIZE(desc), L"Stencil: 0x%08x (%dx%d)", state.getFrameBufRawAddress(), primaryBuffer->GetStride(), primaryBuffer->GetHeight());
|
||||
}
|
||||
bufferResult = GPU_GetCurrentStencilbuffer(primaryBuffer_);
|
||||
break;
|
||||
}
|
||||
|
||||
if (bufferResult && primaryBuffer != NULL) {
|
||||
auto fmt = SimpleGLWindow::Format(primaryBuffer->GetFormat());
|
||||
frameWindow->Draw(primaryBuffer->GetData(), primaryBuffer->GetStride(), primaryBuffer->GetHeight(), primaryBuffer->GetFlipped(), fmt);
|
||||
if (bufferResult && primaryBuffer_ != nullptr) {
|
||||
auto fmt = SimpleGLWindow::Format(primaryBuffer_->GetFormat());
|
||||
frameWindow->Draw(primaryBuffer_->GetData(), primaryBuffer_->GetStride(), primaryBuffer_->GetHeight(), primaryBuffer_->GetFlipped(), fmt);
|
||||
|
||||
DescribeFramebufTab(state, desc);
|
||||
SetDlgItemText(m_hDlg, IDC_GEDBG_FRAMEBUFADDR, desc);
|
||||
} else if (frameWindow != NULL) {
|
||||
frameWindow->Clear();
|
||||
primaryBuffer_ = nullptr;
|
||||
|
||||
SetDlgItemText(m_hDlg, IDC_GEDBG_FRAMEBUFADDR, L"Failed");
|
||||
}
|
||||
|
||||
const GPUDebugBuffer *bufferTex = NULL;
|
||||
texBuffer_ = nullptr;
|
||||
UpdateTextureLevel(textureLevel_);
|
||||
bufferResult = GPU_GetCurrentTexture(bufferTex, textureLevel_);
|
||||
bufferResult = GPU_GetCurrentTexture(texBuffer_, textureLevel_);
|
||||
|
||||
if (bufferResult) {
|
||||
auto fmt = SimpleGLWindow::Format(bufferTex->GetFormat());
|
||||
texWindow->Draw(bufferTex->GetData(), bufferTex->GetStride(), bufferTex->GetHeight(), bufferTex->GetFlipped(), fmt);
|
||||
auto fmt = SimpleGLWindow::Format(texBuffer_->GetFormat());
|
||||
texWindow->Draw(texBuffer_->GetData(), texBuffer_->GetStride(), texBuffer_->GetHeight(), texBuffer_->GetFlipped(), fmt);
|
||||
|
||||
if (gpuDebug != NULL) {
|
||||
if (state.isTextureAlphaUsed()) {
|
||||
@ -210,7 +235,7 @@ void CGEDebugger::UpdatePreviews() {
|
||||
} else {
|
||||
texWindow->SetFlags(SimpleGLWindow::RESIZE_SHRINK_CENTER);
|
||||
}
|
||||
_snwprintf(desc, ARRAY_SIZE(desc), L"Texture L%d: 0x%08x (%dx%d)", textureLevel_, state.getTextureAddress(textureLevel_), state.getTextureWidth(textureLevel_), state.getTextureHeight(textureLevel_));
|
||||
DescribeTexture(state, desc);
|
||||
SetDlgItemText(m_hDlg, IDC_GEDBG_TEXADDR, desc);
|
||||
|
||||
UpdateLastTexture(state.getTextureAddress(textureLevel_));
|
||||
@ -219,6 +244,8 @@ void CGEDebugger::UpdatePreviews() {
|
||||
}
|
||||
} else if (texWindow != NULL) {
|
||||
texWindow->Clear();
|
||||
texBuffer_ = nullptr;
|
||||
|
||||
if (gpuDebug == NULL || state.isTextureMapEnabled()) {
|
||||
SetDlgItemText(m_hDlg, IDC_GEDBG_TEXADDR, L"Texture: failed");
|
||||
} else {
|
||||
@ -248,6 +275,158 @@ void CGEDebugger::UpdatePreviews() {
|
||||
lists->Update();
|
||||
}
|
||||
|
||||
void CGEDebugger::PreviewFramebufHover(int x, int y) {
|
||||
if (primaryBuffer_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
wchar_t desc[256] = {0};
|
||||
|
||||
if (x < 0 || y < 0) {
|
||||
// This means they left the area.
|
||||
GPUgstate state = {0};
|
||||
if (gpuDebug != nullptr) {
|
||||
state = gpuDebug->GetGState();
|
||||
}
|
||||
DescribeFramebufTab(state, desc);
|
||||
} else {
|
||||
// Coordinates are relative to actual framebuffer size.
|
||||
u32 pix = primaryBuffer_->GetRawPixel(x, y);
|
||||
DescribePixel(pix, primaryBuffer_->GetFormat(), x, y, desc);
|
||||
}
|
||||
|
||||
SetDlgItemText(m_hDlg, IDC_GEDBG_FRAMEBUFADDR, desc);
|
||||
}
|
||||
|
||||
void CGEDebugger::DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, wchar_t desc[256]) {
|
||||
switch (fmt) {
|
||||
case GPU_DBG_FORMAT_565:
|
||||
case GPU_DBG_FORMAT_565_REV:
|
||||
case GPU_DBG_FORMAT_5551:
|
||||
case GPU_DBG_FORMAT_5551_REV:
|
||||
case GPU_DBG_FORMAT_5551_BGRA:
|
||||
case GPU_DBG_FORMAT_4444:
|
||||
case GPU_DBG_FORMAT_4444_REV:
|
||||
case GPU_DBG_FORMAT_4444_BGRA:
|
||||
case GPU_DBG_FORMAT_8888:
|
||||
case GPU_DBG_FORMAT_8888_BGRA:
|
||||
DescribePixelRGBA(pix, fmt, x, y, desc);
|
||||
break;
|
||||
|
||||
case GPU_DBG_FORMAT_16BIT:
|
||||
_snwprintf(desc, 256, L"%d,%d: %d", x, y, pix);
|
||||
break;
|
||||
|
||||
case GPU_DBG_FORMAT_8BIT:
|
||||
_snwprintf(desc, 256, L"%d,%d: %d", x, y, pix);
|
||||
break;
|
||||
|
||||
case GPU_DBG_FORMAT_24BIT_8X:
|
||||
_snwprintf(desc, 256, L"%d,%d: %d", x, y, pix & 0x00FFFFFF);
|
||||
break;
|
||||
|
||||
case GPU_DBG_FORMAT_24X_8BIT:
|
||||
_snwprintf(desc, 256, L"%d,%d: %d", x, y, (pix >> 24) & 0xFF);
|
||||
break;
|
||||
|
||||
case GPU_DBG_FORMAT_FLOAT:
|
||||
_snwprintf(desc, 256, L"%d,%d: %f", x, y, *(float *)&pix);
|
||||
break;
|
||||
|
||||
default:
|
||||
_snwprintf(desc, 256, L"Unexpected format");
|
||||
}
|
||||
}
|
||||
|
||||
void CGEDebugger::DescribePixelRGBA(u32 pix, GPUDebugBufferFormat fmt, int x, int y, wchar_t desc[256]) {
|
||||
u32 r = -1, g = -1, b = -1, a = -1;
|
||||
|
||||
switch (fmt) {
|
||||
case GPU_DBG_FORMAT_565:
|
||||
r = Convert5To8((pix >> 0) & 0x1F);
|
||||
g = Convert6To8((pix >> 5) & 0x3F);
|
||||
b = Convert5To8((pix >> 11) & 0x1F);
|
||||
case GPU_DBG_FORMAT_565_REV:
|
||||
b = Convert5To8((pix >> 0) & 0x1F);
|
||||
g = Convert6To8((pix >> 5) & 0x3F);
|
||||
r = Convert5To8((pix >> 11) & 0x1F);
|
||||
case GPU_DBG_FORMAT_5551:
|
||||
r = Convert5To8((pix >> 0) & 0x1F);
|
||||
g = Convert5To8((pix >> 5) & 0x1F);
|
||||
b = Convert5To8((pix >> 10) & 0x1F);
|
||||
a = (pix >> 15) & 1 ? 255 : 0;
|
||||
case GPU_DBG_FORMAT_5551_REV:
|
||||
a = pix & 1 ? 255 : 0;
|
||||
b = Convert5To8((pix >> 1) & 0x1F);
|
||||
g = Convert5To8((pix >> 6) & 0x1F);
|
||||
r = Convert5To8((pix >> 11) & 0x1F);
|
||||
case GPU_DBG_FORMAT_5551_BGRA:
|
||||
b = Convert5To8((pix >> 0) & 0x1F);
|
||||
g = Convert5To8((pix >> 5) & 0x1F);
|
||||
r = Convert5To8((pix >> 10) & 0x1F);
|
||||
a = (pix >> 15) & 1 ? 255 : 0;
|
||||
break;
|
||||
case GPU_DBG_FORMAT_4444:
|
||||
r = Convert4To8((pix >> 0) & 0x0F);
|
||||
g = Convert4To8((pix >> 4) & 0x0F);
|
||||
b = Convert4To8((pix >> 8) & 0x0F);
|
||||
a = Convert4To8((pix >> 12) & 0x0F);
|
||||
break;
|
||||
case GPU_DBG_FORMAT_4444_REV:
|
||||
a = Convert4To8((pix >> 0) & 0x0F);
|
||||
b = Convert4To8((pix >> 4) & 0x0F);
|
||||
g = Convert4To8((pix >> 8) & 0x0F);
|
||||
r = Convert4To8((pix >> 12) & 0x0F);
|
||||
break;
|
||||
case GPU_DBG_FORMAT_4444_BGRA:
|
||||
b = Convert4To8((pix >> 0) & 0x0F);
|
||||
g = Convert4To8((pix >> 4) & 0x0F);
|
||||
r = Convert4To8((pix >> 8) & 0x0F);
|
||||
a = Convert4To8((pix >> 12) & 0x0F);
|
||||
break;
|
||||
case GPU_DBG_FORMAT_8888:
|
||||
r = (pix >> 0) & 0xFF;
|
||||
g = (pix >> 8) & 0xFF;
|
||||
b = (pix >> 16) & 0xFF;
|
||||
a = (pix >> 24) & 0xFF;
|
||||
break;
|
||||
case GPU_DBG_FORMAT_8888_BGRA:
|
||||
b = (pix >> 0) & 0xFF;
|
||||
g = (pix >> 8) & 0xFF;
|
||||
r = (pix >> 16) & 0xFF;
|
||||
a = (pix >> 24) & 0xFF;
|
||||
break;
|
||||
|
||||
default:
|
||||
_snwprintf(desc, 256, L"Unexpected format");
|
||||
return;
|
||||
}
|
||||
|
||||
_snwprintf(desc, 256, L"%d,%d: r=%d, g=%d, b=%d, a=%d", x, y, r, g, b, a);
|
||||
}
|
||||
|
||||
void CGEDebugger::PreviewTextureHover(int x, int y) {
|
||||
if (texBuffer_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
wchar_t desc[256] = {0};
|
||||
|
||||
if (x < 0 || y < 0) {
|
||||
// This means they left the area.
|
||||
GPUgstate state = {0};
|
||||
if (gpuDebug != nullptr) {
|
||||
state = gpuDebug->GetGState();
|
||||
}
|
||||
DescribeTexture(state, desc);
|
||||
} else {
|
||||
u32 pix = texBuffer_->GetRawPixel(x, y);
|
||||
DescribePixel(pix, texBuffer_->GetFormat(), x, y, desc);
|
||||
}
|
||||
|
||||
SetDlgItemText(m_hDlg, IDC_GEDBG_TEXADDR, desc);
|
||||
}
|
||||
|
||||
void CGEDebugger::UpdateTextureLevel(int level) {
|
||||
GPUgstate state = {0};
|
||||
if (gpuDebug != NULL) {
|
||||
|
@ -18,6 +18,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Common/CommonWindows.h"
|
||||
#include "GPU/Common/GPUDebugInterface.h"
|
||||
#include "Globals.h"
|
||||
#include "Windows/resource.h"
|
||||
#include "Windows/W32Util/DialogManager.h"
|
||||
@ -51,6 +52,7 @@ class TabStateTexture;
|
||||
class TabStateSettings;
|
||||
class TabVertices;
|
||||
class TabMatrices;
|
||||
struct GPUgstate;
|
||||
|
||||
class CGEDebugger : public Dialog {
|
||||
public:
|
||||
@ -71,6 +73,14 @@ private:
|
||||
void SavePosition();
|
||||
void SetBreakNext(BreakNextType type);
|
||||
void UpdateTextureLevel(int level);
|
||||
void DescribeFramebufTab(const GPUgstate &state, wchar_t desc[256]);
|
||||
void DescribeDepthbufPixel(int x, int y, wchar_t desc[256]);
|
||||
void DescribeStencilbufPixel(int x, int y, wchar_t desc[256]);
|
||||
void DescribeTexture(const GPUgstate &state, wchar_t desc[256]);
|
||||
void PreviewFramebufHover(int x, int y);
|
||||
void PreviewTextureHover(int x, int y);
|
||||
void DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, wchar_t desc[256]);
|
||||
void DescribePixelRGBA(u32 pix, GPUDebugBufferFormat fmt, int x, int y, wchar_t desc[256]);
|
||||
|
||||
CtrlDisplayListView *displayList;
|
||||
TabDisplayLists *lists;
|
||||
@ -85,6 +95,9 @@ private:
|
||||
TabControl *tabs;
|
||||
TabControl *fbTabs;
|
||||
int textureLevel_;
|
||||
// The most recent primary/framebuffer and texture buffers.
|
||||
const GPUDebugBuffer *primaryBuffer_;
|
||||
const GPUDebugBuffer *texBuffer_;
|
||||
|
||||
int minWidth,minHeight;
|
||||
};
|
||||
|
@ -68,7 +68,7 @@ static const char basic_vs[] =
|
||||
|
||||
SimpleGLWindow::SimpleGLWindow(HWND wnd)
|
||||
: hWnd_(wnd), valid_(false), drawProgram_(nullptr), tex_(0), flags_(0), zoom_(false),
|
||||
dragging_(false), offsetX_(0), offsetY_(0), reformatBuf_(nullptr) {
|
||||
dragging_(false), offsetX_(0), offsetY_(0), reformatBuf_(nullptr), hoverCallback_(nullptr) {
|
||||
SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR) this);
|
||||
}
|
||||
|
||||
@ -434,6 +434,45 @@ bool SimpleGLWindow::ToggleZoom() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SimpleGLWindow::Hover(int mouseX, int mouseY) {
|
||||
if (hoverCallback_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float fw, fh;
|
||||
float x, y;
|
||||
GetContentSize(x, y, fw, fh);
|
||||
|
||||
if (mouseX < x || mouseX >= x + fw || mouseY < y || mouseY >= y + fh) {
|
||||
// Outside of bounds.
|
||||
hoverCallback_(-1, -1);
|
||||
return true;
|
||||
}
|
||||
|
||||
float tx = (mouseX - x) * (tw_ / fw);
|
||||
float ty = (mouseY - y) * (th_ / fh);
|
||||
|
||||
hoverCallback_((int)tx, (int)ty);
|
||||
|
||||
// Find out when they are done.
|
||||
TRACKMOUSEEVENT tracking = {0};
|
||||
tracking.cbSize = sizeof(tracking);
|
||||
tracking.dwFlags = TME_LEAVE;
|
||||
tracking.hwndTrack = hWnd_;
|
||||
TrackMouseEvent(&tracking);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SimpleGLWindow::Leave() {
|
||||
if (hoverCallback_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hoverCallback_(-1, -1);
|
||||
return true;
|
||||
}
|
||||
|
||||
const u8 *SimpleGLWindow::Reformat(const u8 *data, Format fmt, u32 numPixels) {
|
||||
if (!reformatBuf_ || reformatBufSize_ < numPixels) {
|
||||
delete [] reformatBuf_;
|
||||
@ -463,8 +502,19 @@ SimpleGLWindow *SimpleGLWindow::GetFrom(HWND hwnd) {
|
||||
LRESULT CALLBACK SimpleGLWindow::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
|
||||
SimpleGLWindow *win = SimpleGLWindow::GetFrom(hwnd);
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
int mouseX = 0, mouseY = 0;
|
||||
switch (msg) {
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MOUSEMOVE:
|
||||
mouseX = GET_X_LPARAM(lParam);
|
||||
mouseY = GET_Y_LPARAM(lParam);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (msg) {
|
||||
case WM_NCCREATE:
|
||||
win = new SimpleGLWindow(hwnd);
|
||||
|
||||
@ -482,19 +532,28 @@ LRESULT CALLBACK SimpleGLWindow::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPA
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
if (win->DragStart(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))) {
|
||||
if (win->DragStart(mouseX, mouseY)) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
if (win->DragEnd(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))) {
|
||||
if (win->DragEnd(mouseX, mouseY)) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
if (win->DragContinue(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))) {
|
||||
if (win->DragContinue(mouseX, mouseY)) {
|
||||
return 0;
|
||||
}
|
||||
if (win->Hover(mouseX, mouseY)) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_MOUSELEAVE:
|
||||
if (win->Leave()) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/functional.h"
|
||||
#include "gfx_es2/glsl_program.h"
|
||||
#include "Common/CommonWindows.h"
|
||||
#include "Globals.h"
|
||||
@ -92,6 +93,10 @@ struct SimpleGLWindow {
|
||||
|
||||
void GetContentSize(float &x, float &y, float &fw, float &fh);
|
||||
|
||||
void SetHoverCallback(std::function<void(int, int)> hoverCallback) {
|
||||
hoverCallback_ = hoverCallback;
|
||||
}
|
||||
|
||||
static void RegisterClass();
|
||||
protected:
|
||||
void SetupGL();
|
||||
@ -102,6 +107,8 @@ protected:
|
||||
bool DragStart(int mouseX, int mouseY);
|
||||
bool DragContinue(int mouseX, int mouseY);
|
||||
bool DragEnd(int mouseX, int mouseY);
|
||||
bool Hover(int mouseX, int mouseY);
|
||||
bool Leave();
|
||||
bool ToggleZoom();
|
||||
const u8 *Reformat(const u8 *data, Format fmt, u32 numPixels);
|
||||
|
||||
@ -132,4 +139,6 @@ protected:
|
||||
int offsetY_;
|
||||
u32 *reformatBuf_;
|
||||
u32 reformatBufSize_;
|
||||
|
||||
std::function<void(int, int)> hoverCallback_;
|
||||
};
|
@ -154,6 +154,7 @@ EXEC_AND_LIB_FILES := \
|
||||
$(SRC)/GPU/GeDisasm.cpp \
|
||||
$(SRC)/GPU/Common/DepalettizeShaderCommon.cpp \
|
||||
$(SRC)/GPU/Common/FramebufferCommon.cpp \
|
||||
$(SRC)/GPU/Common/GPUDebugInterface.cpp \
|
||||
$(SRC)/GPU/Common/IndexGenerator.cpp.arm \
|
||||
$(SRC)/GPU/Common/SoftwareTransformCommon.cpp.arm \
|
||||
$(SRC)/GPU/Common/VertexDecoderCommon.cpp.arm \
|
||||
|
Loading…
Reference in New Issue
Block a user