Add a basic debug console UI to the devmenu that shows some log scrollback and has a little command line.

Useful for debugging on non-Windows in the future. For now non-mobile only (although may lift that restriction later)
This commit is contained in:
Henrik Rydgard 2015-01-05 01:23:03 +01:00
parent 23893ffba8
commit a9b010b0cd
6 changed files with 139 additions and 5 deletions

View File

@ -103,6 +103,7 @@ LogManager::LogManager() {
consoleLog_ = NULL;
debuggerLog_ = NULL;
#endif
ringLog_ = new RingbufferLogListener();
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) {
log_[i]->SetEnable(true);
@ -113,6 +114,7 @@ LogManager::LogManager() {
if (IsDebuggerPresent() && debuggerLog_ != NULL && LOG_MSC_OUTPUTDEBUG)
log_[i]->AddListener(debuggerLog_);
#endif
log_[i]->AddListener(ringLog_);
#endif
}
}
@ -285,3 +287,18 @@ void DebuggerLogListener::Log(LogTypes::LOG_LEVELS, const char *msg) {
OutputDebugStringUTF8(msg);
#endif
}
void RingbufferLogListener::Log(LogTypes::LOG_LEVELS level, const char *msg) {
if (!enabled_)
return;
levels_[curMessage_] = (u8)level;
int len = (int)strlen(msg);
if (len >= sizeof(messages_[0]))
len = sizeof(messages_[0]) - 1;
memcpy(messages_[curMessage_], msg, len);
messages_[curMessage_][len] = 0;
curMessage_++;
if (curMessage_ >= MAX_LOGS)
curMessage_ -= MAX_LOGS;
count_++;
}

View File

@ -61,6 +61,27 @@ public:
void Log(LogTypes::LOG_LEVELS, const char *msg);
};
class RingbufferLogListener : public LogListener {
public:
RingbufferLogListener() : curMessage_(0), count_(0), enabled_(false) {}
void Log(LogTypes::LOG_LEVELS, const char *msg);
bool IsEnabled() const { return enabled_; }
void SetEnable(bool enable) { enabled_ = enable; }
int GetCount() const { return count_ < MAX_LOGS ? count_ : MAX_LOGS; }
const char *TextAt(int i) { return messages_[(curMessage_ - i - 1) & (MAX_LOGS - 1)]; }
LogTypes::LOG_LEVELS LevelAt(int i) { return (LogTypes::LOG_LEVELS)levels_[(curMessage_ - i - 1) & (MAX_LOGS - 1)]; }
private:
enum { MAX_LOGS = 128 };
char messages_[MAX_LOGS][1024];
u8 levels_[MAX_LOGS];
int curMessage_;
int count_;
bool enabled_;
};
// TODO: A simple buffered log that can be used to display the log in-window
// on Android etc.
// class BufferedLogListener { ... }
@ -105,6 +126,7 @@ private:
FileLogListener *fileLog_;
ConsoleListener *consoleLog_;
DebuggerLogListener *debuggerLog_;
RingbufferLogListener *ringLog_;
static LogManager *logManager_; // Singleton. Ugh.
std::mutex log_lock_;
@ -157,6 +179,10 @@ public:
return debuggerLog_;
}
RingbufferLogListener *GetRingbufferListener() const {
return ringLog_;
}
static LogManager* GetInstance() {
return logManager_;
}

View File

@ -774,9 +774,9 @@ namespace DX9 {
const u32 rh = PSP_CoreParameter().pixelHeight;
const RECT srcRect = {(LONG)(u0 * vfb->renderWidth), (LONG)(v0 * vfb->renderHeight), (LONG)(u1 * vfb->renderWidth), (LONG)(v1 * vfb->renderHeight)};
const RECT dstRect = {x * rw / w, y * rh / h, (x + w) * rw / w, (y + h) * rh / h};
HRESULT hr = fbo_blit_color(vfb->fbo, &srcRect, nullptr, &dstRect, g_Config.iBufFilter == SCALE_LINEAR ? D3DTEXF_LINEAR : D3DTEXF_POINT);
if (FAILED(hr)) {
ERROR_LOG_REPORT_ONCE(blit_fail, G3D, "fbo_blit_color failed on display: %08x", hr);
//HRESULT hr = fbo_blit_color(vfb->fbo, &srcRect, nullptr, &dstRect, g_Config.iBufFilter == SCALE_LINEAR ? D3DTEXF_LINEAR : D3DTEXF_POINT);
//if (FAILED(hr)) {
// ERROR_LOG_REPORT_ONCE(blit_fail, G3D, "fbo_blit_color failed on display: %08x", hr);
dxstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
// These are in the output display coordinates
if (g_Config.iBufFilter == SCALE_LINEAR) {
@ -789,7 +789,7 @@ namespace DX9 {
dxstate.texMipFilter.set(D3DTEXF_NONE);
dxstate.texMipLodBias.set(0);
DrawActiveTexture(colorTexture, x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, false, u0, v0, u1, v1);
}
//}
}
/*
else if (usePostShader_ && extraFBOs_.size() == 1 && !postShaderAtOutputResolution_) {

View File

@ -55,11 +55,25 @@ void DevMenu::CreatePopupContents(UI::ViewGroup *parent) {
I18NCategory *de = GetI18NCategory("Developer");
I18NCategory *sy = GetI18NCategory("System");
#if !defined(MOBILE_DEVICE)
parent->Add(new Choice(de->T("Log View")))->OnClick.Handle(this, &DevMenu::OnLogView);
#endif
parent->Add(new Choice(de->T("Logging Channels")))->OnClick.Handle(this, &DevMenu::OnLogConfig);
parent->Add(new Choice(sy->T("Developer Tools")))->OnClick.Handle(this, &DevMenu::OnDeveloperTools);
parent->Add(new Choice(de->T("Jit Compare")))->OnClick.Handle(this, &DevMenu::OnJitCompare);
parent->Add(new Choice(de->T("Toggle Freeze")))->OnClick.Handle(this, &DevMenu::OnFreezeFrame);
parent->Add(new Choice(de->T("Dump Frame GPU Commands")))->OnClick.Handle(this, &DevMenu::OnDumpFrame);
RingbufferLogListener *ring = LogManager::GetInstance()->GetRingbufferListener();
if (ring) {
ring->SetEnable(true);
}
}
UI::EventReturn DevMenu::OnLogView(UI::EventParams &e) {
UpdateUIState(UISTATE_PAUSEMENU);
screenManager()->push(new LogScreen());
return UI::EVENT_DONE;
}
UI::EventReturn DevMenu::OnLogConfig(UI::EventParams &e) {
@ -100,6 +114,67 @@ void DevMenu::dialogFinished(const Screen *dialog, DialogResult result) {
// screenManager()->finishDialog(this, DR_OK);
}
void LogScreen::UpdateLog() {
using namespace UI;
RingbufferLogListener *ring = LogManager::GetInstance()->GetRingbufferListener();
if (!ring)
return;
vert_->Clear();
for (int i = ring->GetCount() - 1; i >= 0; i--) {
TextView *v = vert_->Add(new TextView(ring->TextAt(i), FLAG_DYNAMIC_ASCII, false));
uint32_t color = 0xFFFFFF;
switch (ring->LevelAt(i)) {
case LogTypes::LDEBUG: color = 0xE0E0E0; break;
case LogTypes::LWARNING: color = 0x50FFFF; break;
case LogTypes::LERROR: color = 0x5050FF; break;
case LogTypes::LNOTICE: color = 0x30FF30; break;
case LogTypes::LINFO: color = 0xFFFFFF; break;
}
v->SetTextColor(0xFF000000 | color);
}
toBottom_ = true;
}
void LogScreen::update(InputState &input) {
UIDialogScreenWithBackground::update(input);
if (toBottom_) {
toBottom_ = false;
scroll_->ScrollToBottom();
}
}
void LogScreen::CreateViews() {
using namespace UI;
I18NCategory *di = GetI18NCategory("Dialog");
LinearLayout *outer = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
root_ = outer;
scroll_ = outer->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0)));
LinearLayout *bottom = outer->Add(new LinearLayout(ORIENT_HORIZONTAL, new LayoutParams(FILL_PARENT, WRAP_CONTENT)));
bottom->Add(new Button(di->T("Back")))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
cmdLine_ = bottom->Add(new TextEdit("", "Command Line", new LinearLayoutParams(1.0)));
cmdLine_->OnEnter.Handle(this, &LogScreen::OnSubmit);
bottom->Add(new Button(di->T("Submit")))->OnClick.Handle(this, &LogScreen::OnSubmit);
vert_ = scroll_->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
vert_->SetSpacing(0);
UpdateLog();
}
UI::EventReturn LogScreen::OnSubmit(UI::EventParams &e) {
std::string cmd = cmdLine_->GetText();
// TODO: Can add all sorts of fun stuff here that we can't be bothered writing proper UI for, like various memdumps etc.
NOTICE_LOG(HLE, "Submitted: %s", cmd.c_str());
UpdateLog();
cmdLine_->SetText("");
cmdLine_->SetFocus();
return UI::EVENT_DONE;
}
void LogConfigScreen::CreateViews() {
using namespace UI;

View File

@ -36,6 +36,7 @@ public:
virtual void dialogFinished(const Screen *dialog, DialogResult result);
protected:
UI::EventReturn OnLogView(UI::EventParams &e);
UI::EventReturn OnLogConfig(UI::EventParams &e);
UI::EventReturn OnJitCompare(UI::EventParams &e);
UI::EventReturn OnFreezeFrame(UI::EventParams &e);
@ -54,6 +55,21 @@ private:
UI::EventReturn OnLogLevelChange(UI::EventParams &e);
};
class LogScreen : public UIDialogScreenWithBackground {
public:
LogScreen() : toBottom_(false) {}
void CreateViews() override;
void update(InputState &input) override;
private:
void UpdateLog();
UI::EventReturn OnSubmit(UI::EventParams &e);
UI::TextEdit *cmdLine_;
UI::LinearLayout *vert_;
UI::ScrollView *scroll_;
bool toBottom_;
};
class LogLevelScreen : public ListPopupScreen {
public:
LogLevelScreen(const std::string &title);

2
native

@ -1 +1 @@
Subproject commit 3ebd4675091e3d08e0da3ad8d3d66d1adff1697a
Subproject commit 40848ae4b64907fec31b2562fc977c043133a275