aboutsummaryrefslogtreecommitdiff
path: root/src/frontend
diff options
context:
space:
mode:
authorRSDuck <RSDuck@users.noreply.github.com>2021-01-24 22:32:02 +0100
committerRSDuck <RSDuck@users.noreply.github.com>2021-01-24 22:32:13 +0100
commitb9a56bc4e47bbb315f88ba5eaa57ce2b3efece73 (patch)
treebd53d6108f5fd9bf60174d21cf80c969271411f3 /src/frontend
parent536902d61088f10acfb4deb38a17ac6f2badc3d3 (diff)
more screen modes
- add support for different aspect ratios - add support for displaying only one screen at once
Diffstat (limited to 'src/frontend')
-rw-r--r--src/frontend/FrontendUtil.h27
-rw-r--r--src/frontend/Util_Video.cpp297
-rw-r--r--src/frontend/qt_sdl/PlatformConfig.cpp4
-rw-r--r--src/frontend/qt_sdl/PlatformConfig.h2
-rw-r--r--src/frontend/qt_sdl/main.cpp110
-rw-r--r--src/frontend/qt_sdl/main.h15
6 files changed, 311 insertions, 144 deletions
diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h
index 83749d3..dfeb356 100644
--- a/src/frontend/FrontendUtil.h
+++ b/src/frontend/FrontendUtil.h
@@ -121,21 +121,36 @@ void EnableCheats(bool enable);
// 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
// * integerScale: force screens to be scaled up at integer scaling factors
// * screenSwap: whether to swap the position of both screens
-void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int rotation, int sizing, int screenGap, bool integerScale, int swapScreens);
-
-// get a 2x3 transform matrix for each screen
+// * 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,
+ int screenGap,
+ bool integerScale,
+ bool swapScreens,
+ float topAspect, float botAspect);
+
+const int MaxScreenTransforms = 3;
+
+// get a 2x3 transform matrix for each screen and whether it's a top or bottom screen
// note: the transform assumes an origin point at the top left of the display,
// X going left and Y going down
// for each screen the source coordinates should be (0,0) and (256,192)
-// 'top' and 'bot' should point each to an array of 6 floats
-void GetScreenTransforms(float* top, float* bot);
+// 'out' should point to an array of 6*MaxScreenTransforms floats
+// 'kind' should point to an array of MaxScreenTransforms ints
+// (0 = indicates top screen, 1 = bottom screen)
+// returns the amount of screens
+int GetScreenTransforms(float* out, int* kind);
// de-transform the provided host display coordinates to get coordinates
// on the bottom screen
-void GetTouchCoords(int& x, int& y);
+bool GetTouchCoords(int& x, int& y);
// initialize the audio utility
diff --git a/src/frontend/Util_Video.cpp b/src/frontend/Util_Video.cpp
index f096311..4265631 100644
--- a/src/frontend/Util_Video.cpp
+++ b/src/frontend/Util_Video.cpp
@@ -31,7 +31,8 @@ namespace Frontend
float TopScreenMtx[6];
float BotScreenMtx[6];
float TouchMtx[6];
-
+bool TopEnable;
+bool BotEnable;
void M23_Identity(float* m)
{
@@ -47,6 +48,13 @@ void M23_Scale(float* m, float s)
m[4] *= s; m[5] *= s;
}
+void M23_Scale(float* m, float x, float y)
+{
+ m[0] *= x; m[1] *= y;
+ m[2] *= x; m[3] *= y;
+ m[4] *= x; m[5] *= y;
+}
+
void M23_RotateFast(float* m, int angle)
{
if (angle == 0) return;
@@ -109,7 +117,14 @@ void M23_Transform(float* m, float& x, float& y)
}
-void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int rotation, int sizing, int screenGap, bool integerScale, int swapScreens)
+void SetupScreenLayout(int screenWidth, int screenHeight,
+ int screenLayout,
+ int rotation,
+ int sizing,
+ int screenGap,
+ bool integerScale,
+ bool swapScreens,
+ float topAspect, float botAspect)
{
float refpoints[4][2] =
{
@@ -130,6 +145,9 @@ void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int
M23_Translate(TopScreenMtx, -256/2, -192/2);
M23_Translate(BotScreenMtx, -256/2, -192/2);
+ M23_Scale(TopScreenMtx, topAspect, 1);
+ M23_Scale(BotScreenMtx, botAspect, 1);
+
// rotation
{
float rotmtx[6];
@@ -145,136 +163,174 @@ void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int
M23_Transform(BotScreenMtx, refpoints[3][0], refpoints[3][1]);
}
- // move screens apart
- {
- int idx = layout == 0 ? 1 : 0;
- float offset =
- (((layout == 0 && (rotation % 2 == 0)) || (layout == 1 && (rotation % 2 == 1))
- ? 192.f : 256.f)
- + screenGap) / 2.f;
- if ((rotation == 1 || rotation == 2) ^ swapScreens)
- offset *= -1.f;
-
- M23_Translate(TopScreenMtx, (idx==0)?-offset:0, (idx==1)?-offset:0);
- M23_Translate(BotScreenMtx, (idx==0)?offset:0, (idx==1)?offset:0);
-
- refpoints[0][idx] -= offset;
- refpoints[1][idx] -= offset;
- refpoints[2][idx] += offset;
- refpoints[3][idx] += offset;
-
- botTrans[idx] = offset;
- }
+ int posRefPointOffset = 0;
+ int posRefPointCount = 4;
- // scale
+ if (sizing == 4 || sizing == 5)
{
- if (sizing == 0)
- {
- float minX = refpoints[0][0], maxX = minX;
- float minY = refpoints[0][1], maxY = minY;
+ float* mtx = sizing == 4 ? TopScreenMtx : BotScreenMtx;
+ int primOffset = sizing == 4 ? 0 : 2;
+ int secOffset = sizing == 5 ? 2 : 0;
- for (int i = 1; i < 4; i++)
- {
- minX = std::min(minX, refpoints[i][0]);
- minY = std::min(minY, refpoints[i][1]);
- maxX = std::max(maxX, refpoints[i][0]);
- maxY = std::max(maxY, refpoints[i][1]);
- }
+ float hSize = fabsf(refpoints[primOffset][0] - refpoints[primOffset+1][0]);
+ float vSize = fabsf(refpoints[primOffset][1] - refpoints[primOffset+1][1]);
+
+ float scale = std::min(screenWidth / hSize, screenHeight / vSize);
+ if (integerScale)
+ scale = floorf(scale);
- float hSize = maxX - minX;
- float vSize = maxY - minY;
+ TopEnable = sizing == 4;
+ BotEnable = sizing == 5;
+ botScale = scale;
- // scale evenly
- float scale = std::min(screenWidth / hSize, screenHeight / vSize);
+ M23_Scale(mtx, scale);
+ refpoints[primOffset][0] *= scale;
+ refpoints[primOffset][1] *= scale;
+ refpoints[primOffset+1][0] *= scale;
+ refpoints[primOffset+1][1] *= scale;
- if (integerScale)
- scale = floor(scale);
+ posRefPointOffset = primOffset;
+ posRefPointCount = 2;
+ }
+ else
+ {
+ TopEnable = BotEnable = true;
+ // move screens apart
+ {
+ int idx = layout == 0 ? 1 : 0;
- M23_Scale(TopScreenMtx, scale);
- M23_Scale(BotScreenMtx, scale);
+ bool moveV = rotation % 2 == layout;
- for (int i = 0; i < 4; i++)
+ float offsetTop = (moveV ? 192 : 256 * topAspect) / 2 + screenGap / 2;
+ float offsetBot = (moveV ? 192 : 256 * botAspect) / 2 + screenGap / 2;
+
+ if ((rotation == 1 || rotation == 2) ^ swapScreens)
{
- refpoints[i][0] *= scale;
- refpoints[i][1] *= scale;
+ offsetTop *= -1;
+ offsetBot *= -1;
}
- botScale = scale;
+ M23_Translate(TopScreenMtx, (idx==0)?-offsetTop:0, (idx==1)?-offsetTop:0);
+ M23_Translate(BotScreenMtx, (idx==0)?offsetBot:0, (idx==1)?offsetBot:0);
+
+ refpoints[0][idx] -= offsetTop;
+ refpoints[1][idx] -= offsetTop;
+ refpoints[2][idx] += offsetBot;
+ refpoints[3][idx] += offsetBot;
+
+ botTrans[idx] = offsetBot;
}
- else
+
+ // scale
{
- int primOffset = (sizing == 1) ? 0 : 2;
- int secOffset = (sizing == 1) ? 2 : 0;
- float* primMtx = (sizing == 1) ? TopScreenMtx : BotScreenMtx;
- float* secMtx = (sizing == 1) ? BotScreenMtx : TopScreenMtx;
+ if (sizing == 0)
+ {
+ float minX = refpoints[0][0], maxX = minX;
+ float minY = refpoints[0][1], maxY = minY;
- float primMinX = refpoints[primOffset][0], primMaxX = primMinX;
- float primMinY = refpoints[primOffset][1], primMaxY = primMinY;
- float secMinX = refpoints[secOffset][0], secMaxX = secMinX;
- float secMinY = refpoints[secOffset][1], secMaxY = secMinY;
+ for (int i = 1; i < 4; i++)
+ {
+ minX = std::min(minX, refpoints[i][0]);
+ minY = std::min(minY, refpoints[i][1]);
+ maxX = std::max(maxX, refpoints[i][0]);
+ maxY = std::max(maxY, refpoints[i][1]);
+ }
- primMinX = std::min(primMinX, refpoints[primOffset+1][0]);
- primMinY = std::min(primMinY, refpoints[primOffset+1][1]);
- primMaxX = std::max(primMaxX, refpoints[primOffset+1][0]);
- primMaxY = std::max(primMaxY, refpoints[primOffset+1][1]);
+ float hSize = maxX - minX;
+ float vSize = maxY - minY;
- secMinX = std::min(secMinX, refpoints[secOffset+1][0]);
- secMinY = std::min(secMinY, refpoints[secOffset+1][1]);
- secMaxX = std::max(secMaxX, refpoints[secOffset+1][0]);
- secMaxY = std::max(secMaxY, refpoints[secOffset+1][1]);
+ // scale evenly
+ float scale = std::min(screenWidth / hSize, screenHeight / vSize);
- float primHSize = layout == 1 ? std::max(primMaxX, -primMinX) : primMaxX - primMinX;
- float primVSize = layout == 0 ? std::max(primMaxY, -primMinY) : primMaxY - primMinY;
+ if (integerScale)
+ scale = floor(scale);
- float secHSize = layout == 1 ? std::max(secMaxX, -secMinX) : secMaxX - secMinX;
- float secVSize = layout == 0 ? std::max(secMaxY, -secMinY) : secMaxY - secMinY;
+ M23_Scale(TopScreenMtx, scale);
+ M23_Scale(BotScreenMtx, scale);
- float primScale = std::min(screenWidth / primHSize, screenHeight / primVSize);
- float secScale = 1.f;
+ for (int i = 0; i < 4; i++)
+ {
+ refpoints[i][0] *= scale;
+ refpoints[i][1] *= scale;
+ }
- if (layout == 0)
- {
- if (screenHeight - primVSize * primScale < secVSize)
- primScale = std::min(screenWidth / primHSize, (screenHeight - secVSize) / primVSize);
- else
- secScale = std::min((screenHeight - primVSize * primScale) / secVSize, screenWidth / secHSize);
+ botScale = scale;
}
else
{
- if (screenWidth - primHSize * primScale < secHSize)
- primScale = std::min((screenWidth - secHSize) / primHSize, screenHeight / primVSize);
+ int primOffset = (sizing == 1) ? 0 : 2;
+ int secOffset = (sizing == 1) ? 2 : 0;
+ float* primMtx = (sizing == 1) ? TopScreenMtx : BotScreenMtx;
+ float* secMtx = (sizing == 1) ? BotScreenMtx : TopScreenMtx;
+
+ float primMinX = refpoints[primOffset][0], primMaxX = primMinX;
+ float primMinY = refpoints[primOffset][1], primMaxY = primMinY;
+ float secMinX = refpoints[secOffset][0], secMaxX = secMinX;
+ float secMinY = refpoints[secOffset][1], secMaxY = secMinY;
+
+ primMinX = std::min(primMinX, refpoints[primOffset+1][0]);
+ primMinY = std::min(primMinY, refpoints[primOffset+1][1]);
+ primMaxX = std::max(primMaxX, refpoints[primOffset+1][0]);
+ primMaxY = std::max(primMaxY, refpoints[primOffset+1][1]);
+
+ secMinX = std::min(secMinX, refpoints[secOffset+1][0]);
+ secMinY = std::min(secMinY, refpoints[secOffset+1][1]);
+ secMaxX = std::max(secMaxX, refpoints[secOffset+1][0]);
+ secMaxY = std::max(secMaxY, refpoints[secOffset+1][1]);
+
+ float primHSize = layout == 1 ? std::max(primMaxX, -primMinX) : primMaxX - primMinX;
+ float primVSize = layout == 0 ? std::max(primMaxY, -primMinY) : primMaxY - primMinY;
+
+ float secHSize = layout == 1 ? std::max(secMaxX, -secMinX) : secMaxX - secMinX;
+ float secVSize = layout == 0 ? std::max(secMaxY, -secMinY) : secMaxY - secMinY;
+
+ float primScale = std::min(screenWidth / primHSize, screenHeight / primVSize);
+ float secScale = 1.f;
+
+ if (layout == 0)
+ {
+ if (screenHeight - primVSize * primScale < secVSize)
+ primScale = std::min(screenWidth / primHSize, (screenHeight - secVSize) / primVSize);
+ else
+ secScale = std::min((screenHeight - primVSize * primScale) / secVSize, screenWidth / secHSize);
+ }
else
- secScale = std::min((screenWidth - primHSize * primScale) / secHSize, screenHeight / secVSize);
+ {
+ if (screenWidth - primHSize * primScale < secHSize)
+ primScale = std::min((screenWidth - secHSize) / primHSize, screenHeight / primVSize);
+ else
+ secScale = std::min((screenWidth - primHSize * primScale) / secHSize, screenHeight / secVSize);
+ }
+
+ if (integerScale)
+ {
+ primScale = floor(primScale);
+ secScale = floor(secScale);
+ }
+
+ M23_Scale(primMtx, primScale);
+ M23_Scale(secMtx, secScale);
+
+ refpoints[primOffset+0][0] *= primScale;
+ refpoints[primOffset+0][1] *= primScale;
+ refpoints[primOffset+1][0] *= primScale;
+ refpoints[primOffset+1][1] *= primScale;
+ refpoints[secOffset+0][0] *= secScale;
+ refpoints[secOffset+0][1] *= secScale;
+ refpoints[secOffset+1][0] *= secScale;
+ refpoints[secOffset+1][1] *= secScale;
+
+ botScale = (sizing == 1) ? secScale : primScale;
}
-
- if (integerScale)
- {
- primScale = floor(primScale);
- secScale = floor(secScale);
- }
-
- M23_Scale(primMtx, primScale);
- M23_Scale(secMtx, secScale);
-
- refpoints[primOffset+0][0] *= primScale;
- refpoints[primOffset+0][1] *= primScale;
- refpoints[primOffset+1][0] *= primScale;
- refpoints[primOffset+1][1] *= primScale;
- refpoints[secOffset+0][0] *= secScale;
- refpoints[secOffset+0][1] *= secScale;
- refpoints[secOffset+1][0] *= secScale;
- refpoints[secOffset+1][1] *= secScale;
-
- botScale = (sizing == 1) ? secScale : primScale;
}
}
// position
{
- float minX = refpoints[0][0], maxX = minX;
- float minY = refpoints[0][1], maxY = minY;
+ float minX = refpoints[posRefPointOffset][0], maxX = minX;
+ float minY = refpoints[posRefPointOffset][1], maxY = minY;
- for (int i = 1; i < 4; i++)
+ for (int i = posRefPointOffset + 1; i < posRefPointOffset + posRefPointCount; i++)
{
minX = std::min(minX, refpoints[i][0]);
minY = std::min(minY, refpoints[i][1]);
@@ -297,6 +353,7 @@ void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int
// prepare a 'reverse' matrix for the touchscreen
// this matrix undoes the transforms applied to the bottom screen
// and can be used to calculate touchscreen coords from host screen coords
+ if (BotEnable)
{
M23_Identity(TouchMtx);
@@ -309,25 +366,45 @@ void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int
M23_RotateFast(rotmtx, (4-rotation) & 3);
M23_Multiply(TouchMtx, rotmtx, TouchMtx);
+ M23_Scale(TouchMtx, 1.f/botAspect, 1);
M23_Translate(TouchMtx, 256/2, 192/2);
}
}
-void GetScreenTransforms(float* top, float* bot)
+int GetScreenTransforms(float* out, int* kind)
{
- memcpy(top, TopScreenMtx, 6*sizeof(float));
- memcpy(bot, BotScreenMtx, 6*sizeof(float));
+ int num = 0;
+ if (TopEnable)
+ {
+ memcpy(out + 6*num, TopScreenMtx, sizeof(TopScreenMtx));
+ kind[num] = 0;
+ num++;
+ }
+ if (BotEnable)
+ {
+ memcpy(out + 6*num, BotScreenMtx, sizeof(BotScreenMtx));
+ kind[num] = 1;
+ num++;
+ }
+ return num;
}
-void GetTouchCoords(int& x, int& y)
+bool GetTouchCoords(int& x, int& y)
{
- float vx = x;
- float vy = y;
+ if (BotEnable)
+ {
+ float vx = x;
+ float vy = y;
- M23_Transform(TouchMtx, vx, vy);
+ M23_Transform(TouchMtx, vx, vy);
- x = (int)vx;
- y = (int)vy;
+ x = (int)vx;
+ y = (int)vy;
+
+ if (x >= 0 && x < 256 && y >= 0 && y < 192)
+ return true;
+ }
+ return false;
}
}
diff --git a/src/frontend/qt_sdl/PlatformConfig.cpp b/src/frontend/qt_sdl/PlatformConfig.cpp
index 0f67b9a..ffab9fb 100644
--- a/src/frontend/qt_sdl/PlatformConfig.cpp
+++ b/src/frontend/qt_sdl/PlatformConfig.cpp
@@ -42,6 +42,8 @@ int ScreenLayout;
int ScreenSwap;
int ScreenSizing;
int IntegerScaling;
+int ScreenAspectTop;
+int ScreenAspectBot;
int ScreenFilter;
int ScreenUseGL;
@@ -146,6 +148,8 @@ ConfigEntry PlatformConfigFile[] =
{"ScreenSwap", 0, &ScreenSwap, 0, NULL, 0},
{"ScreenSizing", 0, &ScreenSizing, 0, NULL, 0},
{"IntegerScaling", 0, &IntegerScaling, 0, NULL, 0},
+ {"ScreenAspectTop",0, &ScreenAspectTop,0, NULL, 0},
+ {"ScreenAspectBot",0, &ScreenAspectBot,0, NULL, 0},
{"ScreenFilter", 0, &ScreenFilter, 1, NULL, 0},
{"ScreenUseGL", 0, &ScreenUseGL, 0, NULL, 0},
diff --git a/src/frontend/qt_sdl/PlatformConfig.h b/src/frontend/qt_sdl/PlatformConfig.h
index bf5fc60..02230ab 100644
--- a/src/frontend/qt_sdl/PlatformConfig.h
+++ b/src/frontend/qt_sdl/PlatformConfig.h
@@ -56,6 +56,8 @@ extern int ScreenGap;
extern int ScreenLayout;
extern int ScreenSwap;
extern int ScreenSizing;
+extern int ScreenAspectTop;
+extern int ScreenAspectBot;
extern int IntegerScaling;
extern int ScreenFilter;
diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp
index baa4716..cc5ef6e 100644
--- a/src/frontend/qt_sdl/main.cpp
+++ b/src/frontend/qt_sdl/main.cpp
@@ -646,15 +646,25 @@ void ScreenHandler::screenSetupLayout(int w, int h)
int sizing = Config::ScreenSizing;
if (sizing == 3) sizing = autoScreenSizing;
+ float aspectRatios[] =
+ {
+ 1.f,
+ (16.f/9)/(4.f/3),
+ (21.f/9)/(4.f/3),
+ ((float)w/h)/(4.f/3)
+ };
+
Frontend::SetupScreenLayout(w, h,
Config::ScreenLayout,
Config::ScreenRotation,
sizing,
Config::ScreenGap,
Config::IntegerScaling != 0,
- Config::ScreenSwap != 0);
+ Config::ScreenSwap != 0,
+ aspectRatios[Config::ScreenAspectTop],
+ aspectRatios[Config::ScreenAspectBot]);
- Frontend::GetScreenTransforms(screenMatrix[0], screenMatrix[1]);
+ numScreens = Frontend::GetScreenTransforms(screenMatrix[0], screenKind);
}
QSize ScreenHandler::screenGetMinSize()
@@ -779,19 +789,16 @@ void ScreenPanelNative::setupScreenLayout()
{
int w = width();
int h = height();
- float* mtx;
screenSetupLayout(w, h);
- mtx = screenMatrix[0];
- screenTrans[0].setMatrix(mtx[0], mtx[1], 0.f,
- mtx[2], mtx[3], 0.f,
- mtx[4], mtx[5], 1.f);
-
- mtx = screenMatrix[1];
- screenTrans[1].setMatrix(mtx[0], mtx[1], 0.f,
- mtx[2], mtx[3], 0.f,
- mtx[4], mtx[5], 1.f);
+ for (int i = 0; i < numScreens; i++)
+ {
+ float* mtx = screenMatrix[i];
+ screenTrans[i].setMatrix(mtx[0], mtx[1], 0.f,
+ mtx[2], mtx[3], 0.f,
+ mtx[4], mtx[5], 1.f);
+ }
}
void ScreenPanelNative::paintEvent(QPaintEvent* event)
@@ -811,11 +818,11 @@ void ScreenPanelNative::paintEvent(QPaintEvent* event)
QRect screenrc(0, 0, 256, 192);
- painter.setTransform(screenTrans[0]);
- painter.drawImage(screenrc, screen[0]);
-
- painter.setTransform(screenTrans[1]);
- painter.drawImage(screenrc, screen[1]);
+ for (int i = 0; i < numScreens; i++)
+ {
+ painter.setTransform(screenTrans[i]);
+ painter.drawImage(screenrc, screen[screenKind[i]]);
+ }
OSD::Update(nullptr);
OSD::DrawNative(painter);
@@ -1002,11 +1009,11 @@ void ScreenPanelGL::paintGL()
GLint transloc = screenShader->uniformLocation("uTransform");
- glUniformMatrix2x3fv(transloc, 1, GL_TRUE, screenMatrix[0]);
- glDrawArrays(GL_TRIANGLES, 0, 2*3);
-
- glUniformMatrix2x3fv(transloc, 1, GL_TRUE, screenMatrix[1]);
- glDrawArrays(GL_TRIANGLES, 2*3, 2*3);
+ for (int i = 0; i < numScreens; i++)
+ {
+ glUniformMatrix2x3fv(transloc, 1, GL_TRUE, screenMatrix[i]);
+ glDrawArrays(GL_TRIANGLES, screenKind[i] == 0 ? 0 : 2*3, 2*3);
+ }
screenShader->release();
@@ -1272,9 +1279,9 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
QMenu* submenu = menu->addMenu("Screen sizing");
grpScreenSizing = new QActionGroup(submenu);
- const char* screensizing[] = {"Even", "Emphasize top", "Emphasize bottom", "Auto"};
+ const char* screensizing[] = {"Even", "Emphasize top", "Emphasize bottom", "Auto", "Top only", "Bottom only"};
- for (int i = 0; i < 4; i++)
+ for (int i = 0; i < 6; i++)
{
actScreenSizing[i] = submenu->addAction(QString(screensizing[i]));
actScreenSizing[i]->setActionGroup(grpScreenSizing);
@@ -1290,6 +1297,38 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actIntegerScaling->setCheckable(true);
connect(actIntegerScaling, &QAction::triggered, this, &MainWindow::onChangeIntegerScaling);
}
+ {
+ QMenu* submenu = menu->addMenu("Aspect ratio");
+ grpScreenAspectTop = new QActionGroup(submenu);
+
+ const char* aspectRatiosTop[] = {"Top 4:3 (native)", "Top 16:9", "Top 21:9", "Top window"};
+
+ for (int i = 0; i < 4; i++)
+ {
+ actScreenAspectTop[i] = submenu->addAction(QString(aspectRatiosTop[i]));
+ actScreenAspectTop[i]->setActionGroup(grpScreenAspectTop);
+ actScreenAspectTop[i]->setData(QVariant(i));
+ actScreenAspectTop[i]->setCheckable(true);
+ }
+
+ connect(grpScreenAspectTop, &QActionGroup::triggered, this, &MainWindow::onChangeScreenAspectTop);
+
+ submenu->addSeparator();
+
+ grpScreenAspectBot = new QActionGroup(submenu);
+
+ const char* aspectRatiosBot[] = {"Bottom 4:3 (native)", "Bottom 16:9", "Bottom 21:9", "Bottom window"};
+
+ for (int i = 0; i < 4; i++)
+ {
+ actScreenAspectBot[i] = submenu->addAction(QString(aspectRatiosBot[i]));
+ actScreenAspectBot[i]->setActionGroup(grpScreenAspectBot);
+ actScreenAspectBot[i]->setData(QVariant(i));
+ actScreenAspectBot[i]->setCheckable(true);
+ }
+
+ connect(grpScreenAspectBot, &QActionGroup::triggered, this, &MainWindow::onChangeScreenAspectBot);
+ }
actScreenFiltering = menu->addAction("Screen filtering");
actScreenFiltering->setCheckable(true);
@@ -1352,6 +1391,9 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actScreenSwap->setChecked(Config::ScreenSwap != 0);
+ actScreenAspectTop[Config::ScreenAspectTop]->setChecked(true);
+ actScreenAspectBot[Config::ScreenAspectBot]->setChecked(true);
+
actScreenFiltering->setChecked(Config::ScreenFilter != 0);
actShowOSD->setChecked(Config::ShowOSD != 0);
@@ -2264,6 +2306,22 @@ void MainWindow::onChangeScreenSizing(QAction* act)
emit screenLayoutChange();
}
+void MainWindow::onChangeScreenAspectTop(QAction* act)
+{
+ int aspect = act->data().toInt();
+ Config::ScreenAspectTop = aspect;
+
+ emit screenLayoutChange();
+}
+
+void MainWindow::onChangeScreenAspectBot(QAction* act)
+{
+ int aspect = act->data().toInt();
+ Config::ScreenAspectBot = aspect;
+
+ emit screenLayoutChange();
+}
+
void MainWindow::onChangeIntegerScaling(bool checked)
{
Config::IntegerScaling = checked?1:0;
@@ -2444,7 +2502,9 @@ int main(int argc, char** argv)
SANITIZE(Config::ScreenRotation, 0, 3);
SANITIZE(Config::ScreenGap, 0, 500);
SANITIZE(Config::ScreenLayout, 0, 2);
- SANITIZE(Config::ScreenSizing, 0, 3);
+ SANITIZE(Config::ScreenSizing, 0, 5);
+ SANITIZE(Config::ScreenAspectTop, 0, 4);
+ SANITIZE(Config::ScreenAspectBot, 0, 4);
#undef SANITIZE
QSurfaceFormat format;
diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h
index ec7bd74..a79c245 100644
--- a/src/frontend/qt_sdl/main.h
+++ b/src/frontend/qt_sdl/main.h
@@ -34,6 +34,7 @@
#include <QOpenGLFunctions_3_2_Core>
#include <QOpenGLShaderProgram>
+#include "FrontendUtil.h"
class EmuThread : public QThread
{
@@ -105,7 +106,9 @@ protected:
void screenOnMouseRelease(QMouseEvent* event);
void screenOnMouseMove(QMouseEvent* event);
- float screenMatrix[2][6];
+ float screenMatrix[Frontend::MaxScreenTransforms][6];
+ int screenKind[Frontend::MaxScreenTransforms];
+ int numScreens;
bool touching;
@@ -137,7 +140,7 @@ private:
void setupScreenLayout();
QImage screen[2];
- QTransform screenTrans[2];
+ QTransform screenTrans[Frontend::MaxScreenTransforms];
};
@@ -237,6 +240,8 @@ private slots:
void onChangeScreenLayout(QAction* act);
void onChangeScreenSwap(bool checked);
void onChangeScreenSizing(QAction* act);
+ void onChangeScreenAspectTop(QAction* act);
+ void onChangeScreenAspectBot(QAction* act);
void onChangeIntegerScaling(bool checked);
void onChangeScreenFiltering(bool checked);
void onChangeShowOSD(bool checked);
@@ -303,8 +308,12 @@ public:
QAction* actScreenLayout[3];
QAction* actScreenSwap;
QActionGroup* grpScreenSizing;
- QAction* actScreenSizing[4];
+ QAction* actScreenSizing[6];
QAction* actIntegerScaling;
+ QActionGroup* grpScreenAspectTop;
+ QAction* actScreenAspectTop[4];
+ QActionGroup* grpScreenAspectBot;
+ QAction* actScreenAspectBot[4];
QAction* actScreenFiltering;
QAction* actShowOSD;
QAction* actLimitFramerate;