From b9a56bc4e47bbb315f88ba5eaa57ce2b3efece73 Mon Sep 17 00:00:00 2001 From: RSDuck Date: Sun, 24 Jan 2021 22:32:02 +0100 Subject: [PATCH] more screen modes - add support for different aspect ratios - add support for displaying only one screen at once --- src/frontend/FrontendUtil.h | 25 +- src/frontend/Util_Video.cpp | 305 ++++++++++++++++--------- src/frontend/qt_sdl/PlatformConfig.cpp | 4 + src/frontend/qt_sdl/PlatformConfig.h | 2 + src/frontend/qt_sdl/main.cpp | 110 +++++++-- src/frontend/qt_sdl/main.h | 15 +- 6 files changed, 314 insertions(+), 147 deletions(-) diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index 83749d3f..dfeb3564 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); +// * 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); -// get a 2x3 transform matrix for each screen +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 f0963117..4265631c 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 posRefPointOffset = 0; + int posRefPointCount = 4; + + if (sizing == 4 || sizing == 5) { - 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; + float* mtx = sizing == 4 ? TopScreenMtx : BotScreenMtx; + int primOffset = sizing == 4 ? 0 : 2; + int secOffset = sizing == 5 ? 2 : 0; - M23_Translate(TopScreenMtx, (idx==0)?-offset:0, (idx==1)?-offset:0); - M23_Translate(BotScreenMtx, (idx==0)?offset:0, (idx==1)?offset:0); + float hSize = fabsf(refpoints[primOffset][0] - refpoints[primOffset+1][0]); + float vSize = fabsf(refpoints[primOffset][1] - refpoints[primOffset+1][1]); - refpoints[0][idx] -= offset; - refpoints[1][idx] -= offset; - refpoints[2][idx] += offset; - refpoints[3][idx] += offset; + float scale = std::min(screenWidth / hSize, screenHeight / vSize); + if (integerScale) + scale = floorf(scale); - botTrans[idx] = offset; + TopEnable = sizing == 4; + BotEnable = sizing == 5; + botScale = scale; + + M23_Scale(mtx, scale); + refpoints[primOffset][0] *= scale; + refpoints[primOffset][1] *= scale; + refpoints[primOffset+1][0] *= scale; + refpoints[primOffset+1][1] *= scale; + + posRefPointOffset = primOffset; + posRefPointCount = 2; } - - // scale + else { - if (sizing == 0) + TopEnable = BotEnable = true; + // move screens apart { - float minX = refpoints[0][0], maxX = minX; - float minY = refpoints[0][1], maxY = minY; + int idx = layout == 0 ? 1 : 0; - for (int i = 1; i < 4; i++) + bool moveV = rotation % 2 == layout; + + float offsetTop = (moveV ? 192 : 256 * topAspect) / 2 + screenGap / 2; + float offsetBot = (moveV ? 192 : 256 * botAspect) / 2 + screenGap / 2; + + if ((rotation == 1 || rotation == 2) ^ swapScreens) { - 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]); + offsetTop *= -1; + offsetBot *= -1; } - float hSize = maxX - minX; - float vSize = maxY - minY; + M23_Translate(TopScreenMtx, (idx==0)?-offsetTop:0, (idx==1)?-offsetTop:0); + M23_Translate(BotScreenMtx, (idx==0)?offsetBot:0, (idx==1)?offsetBot:0); - // scale evenly - float scale = std::min(screenWidth / hSize, screenHeight / vSize); + refpoints[0][idx] -= offsetTop; + refpoints[1][idx] -= offsetTop; + refpoints[2][idx] += offsetBot; + refpoints[3][idx] += offsetBot; - if (integerScale) - scale = floor(scale); - - M23_Scale(TopScreenMtx, scale); - M23_Scale(BotScreenMtx, scale); - - for (int i = 0; i < 4; i++) - { - refpoints[i][0] *= scale; - refpoints[i][1] *= scale; - } - - botScale = scale; + 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; - - 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 (sizing == 0) { - if (screenHeight - primVSize * primScale < secVSize) - primScale = std::min(screenWidth / primHSize, (screenHeight - secVSize) / primVSize); - else - secScale = std::min((screenHeight - primVSize * primScale) / secVSize, screenWidth / secHSize); + float minX = refpoints[0][0], maxX = minX; + float minY = refpoints[0][1], maxY = minY; + + 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 = maxX - minX; + float vSize = maxY - minY; + + // scale evenly + float scale = std::min(screenWidth / hSize, screenHeight / vSize); + + if (integerScale) + scale = floor(scale); + + M23_Scale(TopScreenMtx, scale); + M23_Scale(BotScreenMtx, scale); + + for (int i = 0; i < 4; i++) + { + refpoints[i][0] *= scale; + refpoints[i][1] *= scale; + } + + 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 0f67b9aa..ffab9fb3 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 bf5fc60e..02230ab5 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 baa47160..cc5ef6e2 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 ec7bd74d..a79c245f 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -34,6 +34,7 @@ #include #include +#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;