diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index 18ccc1823f..bec47dee0a 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -59,6 +59,53 @@ enum PrimaryDisplayType { PRIMARY_STENCILBUF, }; +static void *AddDisplayListTab(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, HINSTANCE inst, HWND parent) { + HWND wnd = tabs->AddTabWindow(L"CtrlDisplayListView", tab->name); + return CtrlDisplayListView::getFrom(wnd); +} + +static void RemoveDisplayListTab(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, void *ptr) { + CtrlDisplayListView *view = (CtrlDisplayListView *)ptr; + DestroyWindow(view->GetHWND()); +} + +static void UpdateDisplayListTab(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, void *ptr) { + CtrlDisplayListView *view = (CtrlDisplayListView *)ptr; + DisplayList list; + if (gpuDebug != nullptr && gpuDebug->GetCurrentDisplayList(list)) { + view->setDisplayList(list); + } +} + +template +static void *AddStateTab(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, HINSTANCE inst, HWND parent) { + T *w = new T(inst, parent); + tabs->AddTabDialog(w, tab->name); + return w; +} + +static void RemoveStateTab(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, void *ptr) { + Dialog *view = (Dialog *)ptr; + delete view; +} + +static void UpdateStateTab(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, void *ptr) { + Dialog *view = (Dialog *)ptr; + view->Update(); +} + +static const std::vector defaultTabs = { + { L"Display List", GETabPosition::LEFT, GETabType::LIST_DISASM, {}, &AddDisplayListTab, &RemoveDisplayListTab, &UpdateDisplayListTab }, + { L"Flags", GETabPosition::LEFT, GETabType::STATE, {}, &AddStateTab, &RemoveStateTab, &UpdateStateTab }, + { L"Light", GETabPosition::LEFT, GETabType::STATE, {}, &AddStateTab, &RemoveStateTab, &UpdateStateTab }, + { L"Texture", GETabPosition::LEFT, GETabType::STATE, {}, &AddStateTab, &RemoveStateTab, &UpdateStateTab }, + { L"Settings", GETabPosition::LEFT, GETabType::STATE, {}, &AddStateTab, &RemoveStateTab, &UpdateStateTab }, + { L"Verts", GETabPosition::LEFT, GETabType::STATE, {}, &AddStateTab, &RemoveStateTab, &UpdateStateTab }, + { L"Matrices", GETabPosition::LEFT, GETabType::STATE, {}, &AddStateTab, &RemoveStateTab, &UpdateStateTab }, + { L"Lists", GETabPosition::LEFT, GETabType::LISTS, {}, &AddStateTab, &RemoveStateTab, &UpdateStateTab }, + { L"Watch", GETabPosition::LEFT, GETabType::WATCH, {}, &AddStateTab, &RemoveStateTab, &UpdateStateTab }, +}; + StepCountDlg::StepCountDlg(HINSTANCE _hInstance, HWND _hParent) : Dialog((LPCSTR)IDD_GEDBG_STEPCOUNT, _hInstance, _hParent) { DialogManager::AddDlg(this); @@ -147,9 +194,7 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) tabs = new TabControl(GetDlgItem(m_hDlg, IDC_GEDBG_MAINTAB)); tabsRight_ = new TabControl(GetDlgItem(m_hDlg, IDC_GEDBG_RIGHTTAB)); - - // HWND wnd = tabs->AddTabWindow(L"CtrlDisplayListView", L"Display List"); - displayList = CtrlDisplayListView::Create(m_hDlg); + tabsTR_ = new TabControl(GetDlgItem(m_hDlg, IDC_GEDBG_TOPRIGHTTAB)); fbTabs = new TabControl(GetDlgItem(m_hDlg, IDC_GEDBG_FBTABS)); fbTabs->SetMinTabWidth(50); @@ -159,43 +204,17 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) fbTabs->AddTab(NULL, L"Stencil"); fbTabs->ShowTab(0, true); - flags = new TabStateFlags(_hInstance, m_hDlg); - tabs->AddTabDialog(flags, L"Flags"); + tabStates_ = defaultTabs; + for (GEDebuggerTab &tabState : tabStates_) { + AddTab(&tabState, tabState.pos); + } - lighting = new TabStateLighting(_hInstance, m_hDlg); - tabs->AddTabDialog(lighting, L"Light"); - - textureState = new TabStateTexture(_hInstance, m_hDlg); - tabs->AddTabDialog(textureState, L"Texture"); - - settings = new TabStateSettings(_hInstance, m_hDlg); - tabs->AddTabDialog(settings, L"Settings"); - - vertices = new TabVertices(_hInstance, m_hDlg); - tabs->AddTabDialog(vertices, L"Verts"); - - matrices = new TabMatrices(_hInstance, m_hDlg); - tabs->AddTabDialog(matrices, L"Matrices"); - - lists = new TabDisplayLists(_hInstance, m_hDlg); - tabs->AddTabDialog(lists, L"Lists"); - - watch = new TabStateWatch(_hInstance, m_hDlg); - tabs->AddTabDialog(watch, L"Watch"); - - tabs->ShowTab(0, true); - - - lightingRight_ = new TabStateLighting(_hInstance, m_hDlg); - tabsRight_->AddTabDialog(lightingRight_, L"Light"); - - textureStateRight_ = new TabStateTexture(_hInstance, m_hDlg); - tabsRight_->AddTabDialog(textureStateRight_, L"Texture"); - - settingsRight_ = new TabStateSettings(_hInstance, m_hDlg); - tabsRight_->AddTabDialog(settingsRight_, L"Settings"); - - tabsRight_->ShowTab(0, true); + if (tabs->Count() > 0) + tabs->ShowTab(0, true); + if (tabsRight_->Count() > 0) + tabsRight_->ShowTab(0, true); + if (tabsTR_->Count() > 0) + tabsTR_->ShowTab(0, true); // set window position int x = g_Config.iGEWindowX == -1 ? windowRect.left : g_Config.iGEWindowX; @@ -211,19 +230,14 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) CGEDebugger::~CGEDebugger() { CleanupPrimPreview(); - delete flags; - delete lighting; - delete lightingRight_; - delete textureState; - delete textureStateRight_; - delete settings; - delete settingsRight_; - delete vertices; - delete matrices; - delete lists; - delete watch; + + for (GEDebuggerTab &tabState : tabStates_) { + RemoveTab(&tabState, GETabPosition::ALL); + } + delete tabs; delete tabsRight_; + delete tabsTR_; delete fbTabs; } @@ -370,29 +384,56 @@ void CGEDebugger::UpdatePreviews() { UpdatePrimPreview(primOp, 3); } - DisplayList list; - if (gpuDebug != nullptr && gpuDebug->GetCurrentDisplayList(list)) { - displayList->setDisplayList(list); - } - wchar_t primCounter[1024]{}; swprintf(primCounter, ARRAY_SIZE(primCounter), L"%d/%d", PrimsThisFrame(), PrimsLastFrame()); SetDlgItemText(m_hDlg, IDC_GEDBG_PRIMCOUNTER, primCounter); - flags->Update(); - lighting->Update(); - lightingRight_->Update(); - textureState->Update(); - textureStateRight_->Update(); - settings->Update(); - settingsRight_->Update(); - vertices->Update(); - matrices->Update(); - lists->Update(); - watch->Update(); + for (GEDebuggerTab &tabState : tabStates_) { + UpdateTab(&tabState); + } + updating_ = false; } +void CGEDebugger::UpdateTab(GEDebuggerTab *tab) { + auto doUpdate = [&](GETabPosition pos, TabControl *t, int index) { + if (tab->pos & pos) + tab->update(tab, t, pos, tab->state[index].ptr); + }; + + doUpdate(GETabPosition::LEFT, tabs, 0); + doUpdate(GETabPosition::RIGHT, tabsRight_, 1); + doUpdate(GETabPosition::TOPRIGHT, tabsTR_, 2); +} + +void CGEDebugger::AddTab(GEDebuggerTab *tab, GETabPosition mask) { + auto doAdd = [&](GETabPosition pos, TabControl *t, int index) { + // On init, we still have nullptr, but already have pos, so we use that. + if ((mask & pos) && tab->state[index].ptr == nullptr) { + tab->state[index].ptr = tab->add(tab, t, pos, m_hInstance, m_hDlg); + tab->pos |= pos; + } + }; + + doAdd(GETabPosition::LEFT, tabs, 0); + doAdd(GETabPosition::RIGHT, tabsRight_, 1); + doAdd(GETabPosition::TOPRIGHT, tabsTR_, 2); +} + +void CGEDebugger::RemoveTab(GEDebuggerTab *tab, GETabPosition mask) { + auto doRemove = [&](GETabPosition pos, TabControl *t, int index) { + if ((tab->pos & pos) && (mask & pos)) { + _assert_(tab->state[index].ptr != nullptr); + tab->remove(tab, t, pos, tab->state[index].ptr); + tab->pos = GETabPosition((int)tab->pos & ~(int)pos); + } + }; + + doRemove(GETabPosition::LEFT, tabs, 0); + doRemove(GETabPosition::RIGHT, tabsRight_, 1); + doRemove(GETabPosition::TOPRIGHT, tabsTR_, 2); +} + u32 CGEDebugger::TexturePreviewFlags(const GPUgstate &state) { if (state.isTextureAlphaUsed() && !forceOpaque_) { return SimpleGLWindow::ALPHA_BLEND | SimpleGLWindow::RESIZE_BEST_CENTER; @@ -719,6 +760,7 @@ void CGEDebugger::UpdateSize(WORD width, WORD height) { // only resize the tabs for now HWND tabControl = GetDlgItem(m_hDlg, IDC_GEDBG_MAINTAB); HWND tabControlRight = GetDlgItem(m_hDlg, IDC_GEDBG_RIGHTTAB); + HWND tabControlTR = GetDlgItem(m_hDlg, IDC_GEDBG_TOPRIGHTTAB); RECT tabRect; GetWindowRect(tabControl,&tabRect); @@ -734,14 +776,13 @@ void CGEDebugger::UpdateSize(WORD width, WORD height) { RECT frameRect; HWND frameWnd = GetDlgItem(m_hDlg, IDC_GEDBG_FRAME); GetWindowRect(frameWnd, &frameRect); + MapWindowPoints(HWND_DESKTOP, m_hDlg, (LPPOINT)&frameRect, 2); - RECT listRect = { frameRect.right + 10, 40, tabRectRight.right, tabRect.top }; + RECT trRect = { frameRect.right + 10, frameRect.top, tabRectRight.right, tabRectRight.top }; MoveWindow(tabControl, tabRect.left, tabRect.top, tabRect.right - tabRect.left, tabRect.bottom - tabRect.top, TRUE); MoveWindow(tabControlRight, tabRectRight.left, tabRectRight.top, tabRectRight.right - tabRectRight.left, tabRectRight.bottom - tabRectRight.top, TRUE); - if (displayList) { - MoveWindow(displayList->GetHWND(), listRect.left, listRect.top, listRect.right - listRect.left, listRect.bottom - listRect.top, TRUE); - } + MoveWindow(tabControlTR, trRect.left, trRect.top, trRect.right - trRect.left, trRect.bottom - trRect.top, TRUE); } void CGEDebugger::SavePosition() { @@ -810,12 +851,18 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { case IDC_GEDBG_MAINTAB: tabs->HandleNotify(lParam); if (gpuDebug != nullptr) { - lists->Update(); + for (GEDebuggerTab &tabState : tabStates_) { + if (tabState.type == GETabType::LISTS) + UpdateTab(&tabState); + } } break; case IDC_GEDBG_RIGHTTAB: tabsRight_->HandleNotify(lParam); break; + case IDC_GEDBG_TOPRIGHTTAB: + tabsTR_->HandleNotify(lParam); + break; case IDC_GEDBG_FBTABS: fbTabs->HandleNotify(lParam); if (GPUDebug::IsActive() && gpuDebug != nullptr) { @@ -996,8 +1043,10 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { case WM_GEDBG_UPDATE_WATCH: // Just a notification to update. - if (watch) - watch->Update(); + for (GEDebuggerTab &tabState : tabStates_) { + if (tabState.type == GETabType::WATCH) + UpdateTab(&tabState); + } break; } diff --git a/Windows/GEDebugger/GEDebugger.h b/Windows/GEDebugger/GEDebugger.h index 7dabf9c63c..0e716f1adc 100644 --- a/Windows/GEDebugger/GEDebugger.h +++ b/Windows/GEDebugger/GEDebugger.h @@ -44,6 +44,35 @@ class TabMatrices; class TabStateWatch; struct GPUgstate; +enum class GETabPosition { + LEFT = 1, + RIGHT = 2, + TOPRIGHT = 4, + ALL = 7, +}; +ENUM_CLASS_BITOPS(GETabPosition); + +enum class GETabType { + LIST_DISASM, + LISTS, + STATE, + WATCH, +}; + +struct GEDebuggerTab { + const wchar_t *name; + GETabPosition pos; + GETabType type; + union { + Dialog *dlg; + CtrlDisplayListView *displayList; + void *ptr; + } state[3]; + void *(*add)(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, HINSTANCE inst, HWND parent); + void (*remove)(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, void *ptr); + void (*update)(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, void *ptr); +}; + class StepCountDlg : public Dialog { public: StepCountDlg(HINSTANCE _hInstance, HWND _hParent); @@ -84,25 +113,18 @@ private: static void DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]); static void DescribePixelRGBA(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]); void UpdateMenus(); + void UpdateTab(GEDebuggerTab *tab); + void AddTab(GEDebuggerTab *tab, GETabPosition mask); + void RemoveTab(GEDebuggerTab *tab, GETabPosition mask); u32 TexturePreviewFlags(const GPUgstate &state); - CtrlDisplayListView *displayList = nullptr; - TabDisplayLists *lists = nullptr; - TabStateFlags *flags = nullptr; - TabStateLighting *lighting = nullptr; - TabStateTexture *textureState = nullptr; - TabStateSettings *settings = nullptr; - TabStateLighting *lightingRight_ = nullptr; - TabStateTexture *textureStateRight_ = nullptr; - TabStateSettings *settingsRight_ = nullptr; - TabVertices *vertices = nullptr; - TabMatrices *matrices = nullptr; SimpleGLWindow *primaryWindow = nullptr; SimpleGLWindow *secondWindow = nullptr; - TabStateWatch *watch = nullptr; + std::vector tabStates_; TabControl *tabs = nullptr; TabControl *tabsRight_ = nullptr; + TabControl *tabsTR_ = nullptr; TabControl *fbTabs = nullptr; int textureLevel_ = 0; bool showClut_ = false; diff --git a/Windows/GEDebugger/TabState.h b/Windows/GEDebugger/TabState.h index c60c849028..dbc1558fa0 100644 --- a/Windows/GEDebugger/TabState.h +++ b/Windows/GEDebugger/TabState.h @@ -57,7 +57,7 @@ public: TabStateValues(const TabStateRow *rows, int rowCount, LPCSTR dialogID, HINSTANCE _hInstance, HWND _hParent); ~TabStateValues(); - virtual void Update() { + void Update() override { values->Update(); } diff --git a/Windows/W32Util/DialogManager.h b/Windows/W32Util/DialogManager.h index fc943b3ddd..55497223ac 100644 --- a/Windows/W32Util/DialogManager.h +++ b/Windows/W32Util/DialogManager.h @@ -18,6 +18,7 @@ protected: virtual void Create(); void Destroy(); + HINSTANCE m_hInstance; HWND m_hParent; HWND m_hDlg; LPCSTR m_hResource; @@ -26,9 +27,6 @@ protected: virtual BOOL DlgProc(UINT message, WPARAM wParam, LPARAM lParam) = 0; static INT_PTR CALLBACK DlgProcStatic(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); - -private: - HINSTANCE m_hInstance; }; diff --git a/Windows/W32Util/TabControl.cpp b/Windows/W32Util/TabControl.cpp index 2d315213df..8721a9637c 100644 --- a/Windows/W32Util/TabControl.cpp +++ b/Windows/W32Util/TabControl.cpp @@ -93,6 +93,21 @@ void TabControl::AddTab(HWND handle, const wchar_t* title) ShowTab(index); } +HWND TabControl::RemoveTab(int index) { + int prevIndex = CurrentTabIndex(); + if (currentTab >= index) + --currentTab; + + HWND prevHandle = tabs[index].pageHandle; + TabCtrl_DeleteItem(hwnd, index); + tabs.erase(tabs.begin() + index); + + if (prevIndex == index) + ShowTab(currentTab, true); + + return prevHandle; +} + int TabControl::AppendPageToControl(const wchar_t *title) { TCITEM tcItem; diff --git a/Windows/W32Util/TabControl.h b/Windows/W32Util/TabControl.h index 7eb2360dcf..c8212af004 100644 --- a/Windows/W32Util/TabControl.h +++ b/Windows/W32Util/TabControl.h @@ -14,6 +14,7 @@ public: HWND AddTabWindow(const wchar_t* className, const wchar_t* title, DWORD style = 0); void AddTabDialog(Dialog* dialog, const wchar_t* title); void AddTab(HWND hwnd, const wchar_t* title); + HWND RemoveTab(int index); void ShowTab(int index, bool setControlIndex = true); void ShowTab(HWND pageHandle); void NextTab(bool cycle); @@ -30,6 +31,10 @@ public: bool GetShowTabTitles() { return showTabTitles; } void SetMinTabWidth(int w); + int Count() { + return (int)tabs.size(); + } + private: static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); void OnResize(); diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index cbfb3727b4..80a6295986 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -196,7 +196,7 @@ BEGIN CONTROL "",IDC_DEBUG_BOTTOMTABS,"SysTabControl32",TCS_TABS | TCS_FOCUSNEVER,1,338,513,93 END -IDD_GEDEBUGGER DIALOGEX 0, 0, 500, 400 +IDD_GEDEBUGGER DIALOGEX 0, 0, 490, 400 STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME EXSTYLE WS_EX_ACCEPTFILES | WS_EX_TOOLWINDOW CAPTION "GE" @@ -212,6 +212,7 @@ BEGIN PUSHBUTTON "&Resume",IDC_GEDBG_RESUME,444,2,44,14 CONTROL "",IDC_GEDBG_TEX,"SimpleGLWindow",WS_CHILD | WS_VISIBLE,10,20,128,128 CONTROL "",IDC_GEDBG_FRAME,"SimpleGLWindow",WS_CHILD | WS_VISIBLE,148,20,256,136 + CONTROL "",IDC_GEDBG_TOPRIGHTTAB,"SysTabControl32",TCS_TABS | TCS_FOCUSNEVER,500,20,280,136 CONTROL "",IDC_GEDBG_MAINTAB,"SysTabControl32",TCS_TABS | TCS_FOCUSNEVER,10,216,280,180 CONTROL "",IDC_GEDBG_RIGHTTAB,"SysTabControl32",TCS_TABS | TCS_FOCUSNEVER,210,216,280,180 EDITTEXT IDC_GEDBG_FRAMEBUFADDR,148,192,200,12,ES_READONLY | NOT WS_BORDER diff --git a/Windows/resource.h b/Windows/resource.h index 2b30032234..7cbe5bf9df 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -327,6 +327,7 @@ #define IDC_GEDBG_SETPRIMFILTER 40215 #define IDC_GEDBG_RIGHTTAB 40216 #define ID_OPTIONS_DIRECT3D11 40217 +#define IDC_GEDBG_TOPRIGHTTAB 40218 // Dummy option to let the buffered rendering hotkey cycle through all the options. @@ -340,7 +341,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 256 -#define _APS_NEXT_COMMAND_VALUE 40216 +#define _APS_NEXT_COMMAND_VALUE 40219 #define _APS_NEXT_CONTROL_VALUE 1202 #define _APS_NEXT_SYMED_VALUE 101 #endif