a bit of frontend refactoring

This commit is contained in:
RSDuck
2023-07-29 21:27:28 +02:00
parent 8fd46e5f8c
commit 3efbf1b813
5 changed files with 766 additions and 737 deletions

View File

@ -27,28 +27,48 @@
namespace Frontend
{
enum ScreenLayout
{
screenLayout_Natural, // top screen above bottom screen always
screenLayout_Horizontal,
screenLayout_Vertical,
screenLayout_Hybrid,
screenLayout_MAX,
};
enum ScreenRotation
{
screenRot_0Deg,
screenRot_90Deg,
screenRot_180Deg,
screenRot_270Deg,
screenRot_MAX,
};
enum ScreenSizing
{
screenSizing_Even, // both screens get same size
screenSizing_EmphTop, // make top screen as big as possible, fit bottom screen in remaining space
screenSizing_EmphBot,
screenSizing_Auto, // not applied in SetupScreenLayout
screenSizing_TopOnly,
screenSizing_BotOnly,
screenSizing_MAX,
};
// setup the display layout based on the provided display size and parameters
// * screenWidth/screenHeight: size of the host display
// * screenLayout: how the DS screens are laid out
// 0 = natural (top screen above bottom screen always)
// 1 = vertical
// 2 = horizontal
// 3 = hybrid
// * rotation: angle at which the DS screens are presented: 0/1/2/3 = 0/90/180/270
// * rotation: angle at which the DS screens are presented
// * sizing: how the display size is shared between the two screens
// 0 = even (both screens get same size)
// 1 = emphasize top screen (make top screen as big as possible, fit bottom screen in remaining space)
// 2 = emphasize bottom screen
// 4 = top only
// 5 = bottom only
// * screenGap: size of the gap between the two screens
// * screenGap: size of the gap between the two screens in pixels
// * integerScale: force screens to be scaled up at integer scaling factors
// * screenSwap: whether to swap the position of both screens
// * topAspect/botAspect: ratio by which to scale the top and bottom screen respectively
void SetupScreenLayout(int screenWidth, int screenHeight,
int screenLayout,
int rotation,
int sizing,
ScreenLayout screenLayout,
ScreenRotation rotation,
ScreenSizing sizing,
int screenGap,
bool integerScale,
bool swapScreens,

View File

@ -123,9 +123,9 @@ void M23_Transform(float* m, float& x, float& y)
void SetupScreenLayout(int screenWidth, int screenHeight,
int screenLayout,
int rotation,
int sizing,
ScreenLayout screenLayout,
ScreenRotation rotation,
ScreenSizing sizing,
int screenGap,
bool integerScale,
bool swapScreens,
@ -134,8 +134,8 @@ void SetupScreenLayout(int screenWidth, int screenHeight,
HybEnable = screenLayout == 3;
if (HybEnable)
{
screenLayout = 0;
sizing = 0;
screenLayout = screenLayout_Natural;
sizing = screenSizing_Even;
HybScreen = swapScreens ? 1 : 0;
swapScreens = false;
topAspect = botAspect = 1;
@ -149,7 +149,7 @@ void SetupScreenLayout(int screenWidth, int screenHeight,
{0, 0}, {256, 192}
};
int layout = screenLayout == 0
int layout = screenLayout == screenLayout_Natural
? rotation % 2
: screenLayout - 1;
@ -187,11 +187,11 @@ void SetupScreenLayout(int screenWidth, int screenHeight,
int posRefPointOffset = 0;
int posRefPointCount = HybEnable ? 6 : 4;
if (sizing == 4 || sizing == 5)
if (sizing == screenSizing_TopOnly || sizing == screenSizing_BotOnly)
{
float* mtx = sizing == 4 ? TopScreenMtx : BotScreenMtx;
int primOffset = sizing == 4 ? 0 : 2;
int secOffset = sizing == 5 ? 2 : 0;
float* mtx = sizing == screenSizing_TopOnly ? TopScreenMtx : BotScreenMtx;
int primOffset = sizing == screenSizing_TopOnly ? 0 : 2;
int secOffset = sizing == screenSizing_BotOnly ? 2 : 0;
float hSize = fabsf(refpoints[primOffset][0] - refpoints[primOffset+1][0]);
float vSize = fabsf(refpoints[primOffset][1] - refpoints[primOffset+1][1]);
@ -200,8 +200,8 @@ void SetupScreenLayout(int screenWidth, int screenHeight,
if (integerScale)
scale = floorf(scale);
TopEnable = sizing == 4;
BotEnable = sizing == 5;
TopEnable = sizing == screenSizing_TopOnly;
BotEnable = sizing == screenSizing_BotOnly;
botScale = scale;
M23_Scale(mtx, scale);
@ -245,7 +245,7 @@ void SetupScreenLayout(int screenWidth, int screenHeight,
// scale
{
if (sizing == 0)
if (sizing == screenSizing_Even)
{
float minX = refpoints[0][0], maxX = minX;
float minY = refpoints[0][1], maxY = minY;
@ -299,7 +299,7 @@ void SetupScreenLayout(int screenWidth, int screenHeight,
? (scale * vSize * 4) / 3
: (scale * hSize * 4) / 3;
if (rotation > 1)
if (rotation > screenRot_90Deg)
hybWidth *= -1;
M23_Translate(TopScreenMtx, (layout==0)?hybWidth:0, (layout==1)?hybWidth:0);
@ -311,8 +311,8 @@ void SetupScreenLayout(int screenWidth, int screenHeight,
botTrans[2+layout] += hybWidth;
hybTrans[0] = scale * (rotation == 0 || rotation == 3 ? minX : maxX);
hybTrans[1] = scale * (rotation == 0 || rotation == 1 ? minY : maxY);
hybTrans[0] = scale * (rotation == screenRot_0Deg || rotation == screenRot_270Deg ? minX : maxX);
hybTrans[1] = scale * (rotation == screenRot_0Deg || rotation == screenRot_90Deg ? minY : maxY);
M23_Translate(HybScreenMtx, hybTrans[0], hybTrans[1]);
M23_Transform(HybScreenMtx, refpoints[4][0], refpoints[4][1]);
@ -321,10 +321,10 @@ void SetupScreenLayout(int screenWidth, int screenHeight,
}
else
{
int primOffset = (sizing == 1) ? 0 : 2;
int secOffset = (sizing == 1) ? 2 : 0;
float* primMtx = (sizing == 1) ? TopScreenMtx : BotScreenMtx;
float* secMtx = (sizing == 1) ? BotScreenMtx : TopScreenMtx;
int primOffset = (sizing == screenSizing_EmphTop) ? 0 : 2;
int secOffset = (sizing == screenSizing_EmphTop) ? 2 : 0;
float* primMtx = (sizing == screenSizing_EmphTop) ? TopScreenMtx : BotScreenMtx;
float* secMtx = (sizing == screenSizing_EmphTop) ? BotScreenMtx : TopScreenMtx;
float primMinX = refpoints[primOffset][0], primMaxX = primMinX;
float primMinY = refpoints[primOffset][1], primMaxY = primMinY;
@ -386,7 +386,7 @@ void SetupScreenLayout(int screenWidth, int screenHeight,
refpoints[secOffset+1][0] *= secScale;
refpoints[secOffset+1][1] *= secScale;
botScale = (sizing == 1) ? secScale : primScale;
botScale = (sizing == screenSizing_EmphTop) ? secScale : primScale;
}
}
}

View File

@ -42,17 +42,6 @@ enum
HK_MAX
};
enum
{
screenSizing_Even,
screenSizing_EmphTop,
screenSizing_EmphBot,
screenSizing_Auto,
screenSizing_TopOnly,
screenSizing_BotOnly,
screenSizing_MAX,
};
enum
{
micInputType_Silence,

View File

@ -174,13 +174,14 @@ const struct { int id; float ratio; const char* label; } aspectRatios[] =
{ 2, (21.f / 9) / (4.f / 3), "21:9" },
{ 3, 0, "window" }
};
constexpr int AspectRatiosNum = sizeof(aspectRatios) / sizeof(aspectRatios[0]);
EmuThread::EmuThread(QObject* parent) : QThread(parent)
{
EmuStatus = 0;
EmuRunning = 2;
EmuPause = 0;
EmuStatus = emuStatus_Exit;
EmuRunning = emuStatus_Paused;
EmuPauseStack = EmuPauseStackRunning;
RunningSomething = false;
connect(this, SIGNAL(windowUpdate()), mainWindow->panelWidget, SLOT(repaint()));
@ -353,7 +354,7 @@ void EmuThread::run()
char melontitle[100];
while (EmuRunning != 0)
while (EmuRunning != emuStatus_Exit)
{
Input::Process();
@ -425,10 +426,10 @@ void EmuThread::run()
DSi_BPTWL::ProcessVolumeSwitchInput(currentTime);
}
if (EmuRunning == 1 || EmuRunning == 3)
if (EmuRunning == emuStatus_Running || EmuRunning == emuStatus_FrameStep)
{
EmuStatus = 1;
if (EmuRunning == 3) EmuRunning = 2;
EmuStatus = emuStatus_Running;
if (EmuRunning == emuStatus_FrameStep) EmuRunning = emuStatus_Paused;
// update render settings if needed
// HACK:
@ -473,7 +474,7 @@ void EmuThread::run()
AudioInOut::MicProcess();
// auto screen layout
if (Config::ScreenSizing == screenSizing_Auto)
if (Config::ScreenSizing == Frontend::screenSizing_Auto)
{
mainScreenPos[2] = mainScreenPos[1];
mainScreenPos[1] = mainScreenPos[0];
@ -485,14 +486,14 @@ void EmuThread::run()
{
// constant flickering, likely displaying 3D on both screens
// TODO: when both screens are used for 2D only...???
guess = screenSizing_Even;
guess = Frontend::screenSizing_Even;
}
else
{
if (mainScreenPos[0] == 1)
guess = screenSizing_EmphTop;
guess = Frontend::screenSizing_EmphTop;
else
guess = screenSizing_EmphBot;
guess = Frontend::screenSizing_EmphBot;
}
if (guess != autoScreenSizing)
@ -528,7 +529,7 @@ void EmuThread::run()
MelonCap::Update();
#endif // MELONCAP
if (EmuRunning == 0) break;
if (EmuRunning == emuStatus_Exit) break;
winUpdateCount++;
if (winUpdateCount >= winUpdateFreq && !oglContext)
@ -632,21 +633,21 @@ void EmuThread::run()
if (oglContext)
drawScreenGL();
int contextRequest = ContextRequest;
if (contextRequest == 1)
ContextRequestKind contextRequest = ContextRequest;
if (contextRequest == contextRequest_InitGL)
{
initOpenGL();
ContextRequest = 0;
ContextRequest = contextRequest_None;
}
else if (contextRequest == 2)
else if (contextRequest == contextRequest_DeInitGL)
{
deinitOpenGL();
ContextRequest = 0;
ContextRequest = contextRequest_None;
}
}
}
EmuStatus = 0;
EmuStatus = emuStatus_Exit;
GPU::DeInitRenderer();
NDS::DeInit();
@ -660,8 +661,8 @@ void EmuThread::changeWindowTitle(char* title)
void EmuThread::emuRun()
{
EmuRunning = 1;
EmuPause = 0;
EmuRunning = emuStatus_Running;
EmuPauseStack = EmuPauseStackRunning;
RunningSomething = true;
// checkme
@ -671,34 +672,34 @@ void EmuThread::emuRun()
void EmuThread::initContext()
{
ContextRequest = 1;
while (ContextRequest != 0);
ContextRequest = contextRequest_InitGL;
while (ContextRequest != contextRequest_None);
}
void EmuThread::deinitContext()
{
ContextRequest = 2;
while (ContextRequest != 0);
ContextRequest = contextRequest_DeInitGL;
while (ContextRequest != contextRequest_None);
}
void EmuThread::emuPause()
{
EmuPause++;
if (EmuPause > 1) return;
EmuPauseStack++;
if (EmuPauseStack > EmuPauseStackPauseThreshold) return;
PrevEmuStatus = EmuRunning;
EmuRunning = 2;
while (EmuStatus != 2);
EmuRunning = emuStatus_Paused;
while (EmuStatus != emuStatus_Paused);
AudioInOut::Disable();
}
void EmuThread::emuUnpause()
{
if (EmuPause < 1) return;
if (EmuPauseStack < EmuPauseStackPauseThreshold) return;
EmuPause--;
if (EmuPause > 0) return;
EmuPauseStack--;
if (EmuPauseStack >= EmuPauseStackPauseThreshold) return;
EmuRunning = PrevEmuStatus;
@ -707,21 +708,21 @@ void EmuThread::emuUnpause()
void EmuThread::emuStop()
{
EmuRunning = 0;
EmuPause = 0;
EmuRunning = emuStatus_Exit;
EmuPauseStack = EmuPauseStackRunning;
AudioInOut::Disable();
}
void EmuThread::emuFrameStep()
{
if (EmuPause < 1) emit windowEmuPause();
EmuRunning = 3;
if (EmuPauseStack < EmuPauseStackPauseThreshold) emit windowEmuPause();
EmuRunning = emuStatus_FrameStep;
}
bool EmuThread::emuIsRunning()
{
return (EmuRunning == 1);
return EmuRunning == emuStatus_Running;
}
bool EmuThread::emuIsActive()
@ -830,9 +831,9 @@ void ScreenHandler::screenSetupLayout(int w, int h)
aspectBot = ((float) w / h) / (4.f / 3.f);
Frontend::SetupScreenLayout(w, h,
Config::ScreenLayout,
Config::ScreenRotation,
sizing,
static_cast<Frontend::ScreenLayout>(Config::ScreenLayout),
static_cast<Frontend::ScreenRotation>(Config::ScreenRotation),
static_cast<Frontend::ScreenSizing>(sizing),
Config::ScreenGap,
Config::IntegerScaling != 0,
Config::ScreenSwap != 0,
@ -844,32 +845,34 @@ void ScreenHandler::screenSetupLayout(int w, int h)
QSize ScreenHandler::screenGetMinSize(int factor = 1)
{
bool isHori = (Config::ScreenRotation == 1 || Config::ScreenRotation == 3);
bool isHori = (Config::ScreenRotation == Frontend::screenRot_90Deg
|| Config::ScreenRotation == Frontend::screenRot_270Deg);
int gap = Config::ScreenGap * factor;
int w = 256 * factor;
int h = 192 * factor;
if (Config::ScreenSizing == 4 || Config::ScreenSizing == 5)
if (Config::ScreenSizing == Frontend::screenSizing_TopOnly
|| Config::ScreenSizing == Frontend::screenSizing_BotOnly)
{
return QSize(w, h);
}
if (Config::ScreenLayout == 0) // natural
if (Config::ScreenLayout == Frontend::screenLayout_Natural)
{
if (isHori)
return QSize(h+gap+h, w);
else
return QSize(w, h+gap+h);
}
else if (Config::ScreenLayout == 1) // vertical
else if (Config::ScreenLayout == Frontend::screenLayout_Vertical)
{
if (isHori)
return QSize(h, w+gap+w);
else
return QSize(w, h+gap+h);
}
else if (Config::ScreenLayout == 2) // horizontal
else if (Config::ScreenLayout == Frontend::screenLayout_Horizontal)
{
if (isHori)
return QSize(h+gap+h, w);
@ -1610,7 +1613,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
QMenu* submenu = menu->addMenu("Screen rotation");
grpScreenRotation = new QActionGroup(submenu);
for (int i = 0; i < 4; i++)
for (int i = 0; i < Frontend::screenRot_MAX; i++)
{
int data = i*90;
actScreenRotation[i] = submenu->addAction(QString("%1°").arg(data));
@ -1644,7 +1647,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
const char* screenlayout[] = {"Natural", "Vertical", "Horizontal", "Hybrid"};
for (int i = 0; i < 4; i++)
for (int i = 0; i < Frontend::screenLayout_MAX; i++)
{
actScreenLayout[i] = submenu->addAction(QString(screenlayout[i]));
actScreenLayout[i]->setActionGroup(grpScreenLayout);
@ -1666,7 +1669,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
const char* screensizing[] = {"Even", "Emphasize top", "Emphasize bottom", "Auto", "Top only", "Bottom only"};
for (int i = 0; i < screenSizing_MAX; i++)
for (int i = 0; i < Frontend::screenSizing_MAX; i++)
{
actScreenSizing[i] = submenu->addAction(QString(screensizing[i]));
actScreenSizing[i]->setActionGroup(grpScreenSizing);
@ -1686,8 +1689,8 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
QMenu* submenu = menu->addMenu("Aspect ratio");
grpScreenAspectTop = new QActionGroup(submenu);
grpScreenAspectBot = new QActionGroup(submenu);
actScreenAspectTop = new QAction*[sizeof(aspectRatios) / sizeof(aspectRatios[0])];
actScreenAspectBot = new QAction*[sizeof(aspectRatios) / sizeof(aspectRatios[0])];
actScreenAspectTop = new QAction*[AspectRatiosNum];
actScreenAspectBot = new QAction*[AspectRatiosNum];
for (int i = 0; i < 2; i++)
{
@ -1701,7 +1704,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actions = actScreenAspectBot;
}
for (int j = 0; j < sizeof(aspectRatios) / sizeof(aspectRatios[0]); j++)
for (int j = 0; j < AspectRatiosNum; j++)
{
auto ratio = aspectRatios[j];
QString label = QString("%1 %2").arg(i ? "Bottom" : "Top", ratio.label);
@ -1806,7 +1809,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actScreenSwap->setChecked(Config::ScreenSwap);
for (int i = 0; i < sizeof(aspectRatios) / sizeof(aspectRatios[0]); i++)
for (int i = 0; i < AspectRatiosNum; i++)
{
if (Config::ScreenAspectTop == aspectRatios[i].id)
actScreenAspectTop[i]->setChecked(true);
@ -3011,18 +3014,18 @@ void MainWindow::onChangeScreenSwap(bool checked)
Config::ScreenSwap = checked?1:0;
// Swap between top and bottom screen when displaying one screen.
if (Config::ScreenSizing == screenSizing_TopOnly)
if (Config::ScreenSizing == Frontend::screenSizing_TopOnly)
{
// Bottom Screen.
Config::ScreenSizing = screenSizing_BotOnly;
actScreenSizing[screenSizing_TopOnly]->setChecked(false);
Config::ScreenSizing = Frontend::screenSizing_BotOnly;
actScreenSizing[Frontend::screenSizing_TopOnly]->setChecked(false);
actScreenSizing[Config::ScreenSizing]->setChecked(true);
}
else if (Config::ScreenSizing == screenSizing_BotOnly)
else if (Config::ScreenSizing == Frontend::screenSizing_BotOnly)
{
// Top Screen.
Config::ScreenSizing = screenSizing_TopOnly;
actScreenSizing[screenSizing_BotOnly]->setChecked(false);
Config::ScreenSizing = Frontend::screenSizing_TopOnly;
actScreenSizing[Frontend::screenSizing_BotOnly]->setChecked(false);
actScreenSizing[Config::ScreenSizing]->setChecked(true);
}
@ -3111,13 +3114,13 @@ void MainWindow::onFullscreenToggled()
void MainWindow::onScreenEmphasisToggled()
{
int currentSizing = Config::ScreenSizing;
if (currentSizing == screenSizing_EmphTop)
if (currentSizing == Frontend::screenSizing_EmphTop)
{
Config::ScreenSizing = screenSizing_EmphBot;
Config::ScreenSizing = Frontend::screenSizing_EmphBot;
}
else if (currentSizing == screenSizing_EmphBot)
else if (currentSizing == Frontend::screenSizing_EmphBot)
{
Config::ScreenSizing = screenSizing_EmphTop;
Config::ScreenSizing = Frontend::screenSizing_EmphTop;
}
emit screenLayoutChange();
@ -3279,12 +3282,12 @@ int main(int argc, char** argv)
SANITIZE(Config::AudioInterp, 0, 3);
SANITIZE(Config::AudioVolume, 0, 256);
SANITIZE(Config::MicInputType, 0, (int)micInputType_MAX);
SANITIZE(Config::ScreenRotation, 0, 3);
SANITIZE(Config::ScreenRotation, 0, (int)Frontend::screenRot_MAX);
SANITIZE(Config::ScreenGap, 0, 500);
SANITIZE(Config::ScreenLayout, 0, 3);
SANITIZE(Config::ScreenSizing, 0, (int)screenSizing_MAX);
SANITIZE(Config::ScreenAspectTop, 0, 4);
SANITIZE(Config::ScreenAspectBot, 0, 4);
SANITIZE(Config::ScreenLayout, 0, (int)Frontend::screenLayout_MAX);
SANITIZE(Config::ScreenSizing, 0, (int)Frontend::screenSizing_MAX);
SANITIZE(Config::ScreenAspectTop, 0, AspectRatiosNum);
SANITIZE(Config::ScreenAspectBot, 0, AspectRatiosNum);
#undef SANITIZE
AudioInOut::Init();

View File

@ -94,12 +94,29 @@ private:
void initOpenGL();
void deinitOpenGL();
std::atomic<int> EmuStatus;
int PrevEmuStatus;
int EmuRunning;
int EmuPause;
enum EmuStatusKind
{
emuStatus_Exit,
emuStatus_Running,
emuStatus_Paused,
emuStatus_FrameStep,
};
std::atomic<EmuStatusKind> EmuStatus;
std::atomic<int> ContextRequest = 0;
EmuStatusKind PrevEmuStatus;
EmuStatusKind EmuRunning;
constexpr static int EmuPauseStackRunning = 0;
constexpr static int EmuPauseStackPauseThreshold = 1;
int EmuPauseStack;
enum ContextRequestKind
{
contextRequest_None = 0,
contextRequest_InitGL,
contextRequest_DeInitGL
};
std::atomic<ContextRequestKind> ContextRequest = contextRequest_None;
GL::Context* oglContext = nullptr;
GLuint screenVertexBuffer, screenVertexArray;
@ -404,14 +421,14 @@ public:
QAction* actSavestateSRAMReloc;
QAction* actScreenSize[4];
QActionGroup* grpScreenRotation;
QAction* actScreenRotation[4];
QAction* actScreenRotation[Frontend::screenRot_MAX];
QActionGroup* grpScreenGap;
QAction* actScreenGap[6];
QActionGroup* grpScreenLayout;
QAction* actScreenLayout[4];
QAction* actScreenLayout[Frontend::screenLayout_MAX];
QAction* actScreenSwap;
QActionGroup* grpScreenSizing;
QAction* actScreenSizing[6];
QAction* actScreenSizing[Frontend::screenSizing_MAX];
QAction* actIntegerScaling;
QActionGroup* grpScreenAspectTop;
QAction** actScreenAspectTop;