more screen modes

- add support for different aspect ratios
- add support for displaying only one screen at once
This commit is contained in:
RSDuck 2021-01-24 22:32:02 +01:00
parent 536902d610
commit b9a56bc4e4
6 changed files with 314 additions and 147 deletions

View File

@ -121,21 +121,36 @@ void EnableCheats(bool enable);
// 0 = even (both screens get same size) // 0 = even (both screens get same size)
// 1 = emphasize top screen (make top screen as big as possible, fit bottom screen in remaining space) // 1 = emphasize top screen (make top screen as big as possible, fit bottom screen in remaining space)
// 2 = emphasize bottom screen // 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
// * integerScale: force screens to be scaled up at integer scaling factors // * integerScale: force screens to be scaled up at integer scaling factors
// * screenSwap: whether to swap the position of both screens // * 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, // note: the transform assumes an origin point at the top left of the display,
// X going left and Y going down // X going left and Y going down
// for each screen the source coordinates should be (0,0) and (256,192) // 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 // 'out' should point to an array of 6*MaxScreenTransforms floats
void GetScreenTransforms(float* top, float* bot); // '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 // de-transform the provided host display coordinates to get coordinates
// on the bottom screen // on the bottom screen
void GetTouchCoords(int& x, int& y); bool GetTouchCoords(int& x, int& y);
// initialize the audio utility // initialize the audio utility

View File

@ -31,7 +31,8 @@ namespace Frontend
float TopScreenMtx[6]; float TopScreenMtx[6];
float BotScreenMtx[6]; float BotScreenMtx[6];
float TouchMtx[6]; float TouchMtx[6];
bool TopEnable;
bool BotEnable;
void M23_Identity(float* m) void M23_Identity(float* m)
{ {
@ -47,6 +48,13 @@ void M23_Scale(float* m, float s)
m[4] *= s; m[5] *= 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) void M23_RotateFast(float* m, int angle)
{ {
if (angle == 0) return; 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] = 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(TopScreenMtx, -256/2, -192/2);
M23_Translate(BotScreenMtx, -256/2, -192/2); M23_Translate(BotScreenMtx, -256/2, -192/2);
M23_Scale(TopScreenMtx, topAspect, 1);
M23_Scale(BotScreenMtx, botAspect, 1);
// rotation // rotation
{ {
float rotmtx[6]; 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]); 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* mtx = sizing == 4 ? TopScreenMtx : BotScreenMtx;
float offset = int primOffset = sizing == 4 ? 0 : 2;
(((layout == 0 && (rotation % 2 == 0)) || (layout == 1 && (rotation % 2 == 1)) int secOffset = sizing == 5 ? 2 : 0;
? 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); float hSize = fabsf(refpoints[primOffset][0] - refpoints[primOffset+1][0]);
M23_Translate(BotScreenMtx, (idx==0)?offset:0, (idx==1)?offset:0); float vSize = fabsf(refpoints[primOffset][1] - refpoints[primOffset+1][1]);
refpoints[0][idx] -= offset; float scale = std::min(screenWidth / hSize, screenHeight / vSize);
refpoints[1][idx] -= offset; if (integerScale)
refpoints[2][idx] += offset; scale = floorf(scale);
refpoints[3][idx] += offset;
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;
} }
else
// scale
{ {
if (sizing == 0) TopEnable = BotEnable = true;
// move screens apart
{ {
float minX = refpoints[0][0], maxX = minX; int idx = layout == 0 ? 1 : 0;
float minY = refpoints[0][1], maxY = minY;
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]); offsetTop *= -1;
minY = std::min(minY, refpoints[i][1]); offsetBot *= -1;
maxX = std::max(maxX, refpoints[i][0]);
maxY = std::max(maxY, refpoints[i][1]);
} }
float hSize = maxX - minX; M23_Translate(TopScreenMtx, (idx==0)?-offsetTop:0, (idx==1)?-offsetTop:0);
float vSize = maxY - minY; M23_Translate(BotScreenMtx, (idx==0)?offsetBot:0, (idx==1)?offsetBot:0);
// scale evenly refpoints[0][idx] -= offsetTop;
float scale = std::min(screenWidth / hSize, screenHeight / vSize); refpoints[1][idx] -= offsetTop;
refpoints[2][idx] += offsetBot;
refpoints[3][idx] += offsetBot;
if (integerScale) botTrans[idx] = offsetBot;
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
// scale
{ {
int primOffset = (sizing == 1) ? 0 : 2; if (sizing == 0)
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) float minX = refpoints[0][0], maxX = minX;
primScale = std::min(screenWidth / primHSize, (screenHeight - secVSize) / primVSize); float minY = refpoints[0][1], maxY = minY;
else
secScale = std::min((screenHeight - primVSize * primScale) / secVSize, screenWidth / secHSize); 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 else
{ {
if (screenWidth - primHSize * primScale < secHSize) int primOffset = (sizing == 1) ? 0 : 2;
primScale = std::min((screenWidth - secHSize) / primHSize, screenHeight / primVSize); 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 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 // position
{ {
float minX = refpoints[0][0], maxX = minX; float minX = refpoints[posRefPointOffset][0], maxX = minX;
float minY = refpoints[0][1], maxY = minY; 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]); minX = std::min(minX, refpoints[i][0]);
minY = std::min(minY, refpoints[i][1]); 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 // prepare a 'reverse' matrix for the touchscreen
// this matrix undoes the transforms applied to the bottom screen // this matrix undoes the transforms applied to the bottom screen
// and can be used to calculate touchscreen coords from host screen coords // and can be used to calculate touchscreen coords from host screen coords
if (BotEnable)
{ {
M23_Identity(TouchMtx); M23_Identity(TouchMtx);
@ -309,25 +366,45 @@ void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int
M23_RotateFast(rotmtx, (4-rotation) & 3); M23_RotateFast(rotmtx, (4-rotation) & 3);
M23_Multiply(TouchMtx, rotmtx, TouchMtx); M23_Multiply(TouchMtx, rotmtx, TouchMtx);
M23_Scale(TouchMtx, 1.f/botAspect, 1);
M23_Translate(TouchMtx, 256/2, 192/2); 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)); int num = 0;
memcpy(bot, BotScreenMtx, 6*sizeof(float)); 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; if (BotEnable)
float vy = y; {
float vx = x;
float vy = y;
M23_Transform(TouchMtx, vx, vy); M23_Transform(TouchMtx, vx, vy);
x = (int)vx; x = (int)vx;
y = (int)vy; y = (int)vy;
if (x >= 0 && x < 256 && y >= 0 && y < 192)
return true;
}
return false;
} }
} }

View File

@ -42,6 +42,8 @@ int ScreenLayout;
int ScreenSwap; int ScreenSwap;
int ScreenSizing; int ScreenSizing;
int IntegerScaling; int IntegerScaling;
int ScreenAspectTop;
int ScreenAspectBot;
int ScreenFilter; int ScreenFilter;
int ScreenUseGL; int ScreenUseGL;
@ -146,6 +148,8 @@ ConfigEntry PlatformConfigFile[] =
{"ScreenSwap", 0, &ScreenSwap, 0, NULL, 0}, {"ScreenSwap", 0, &ScreenSwap, 0, NULL, 0},
{"ScreenSizing", 0, &ScreenSizing, 0, NULL, 0}, {"ScreenSizing", 0, &ScreenSizing, 0, NULL, 0},
{"IntegerScaling", 0, &IntegerScaling, 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}, {"ScreenFilter", 0, &ScreenFilter, 1, NULL, 0},
{"ScreenUseGL", 0, &ScreenUseGL, 0, NULL, 0}, {"ScreenUseGL", 0, &ScreenUseGL, 0, NULL, 0},

View File

@ -56,6 +56,8 @@ extern int ScreenGap;
extern int ScreenLayout; extern int ScreenLayout;
extern int ScreenSwap; extern int ScreenSwap;
extern int ScreenSizing; extern int ScreenSizing;
extern int ScreenAspectTop;
extern int ScreenAspectBot;
extern int IntegerScaling; extern int IntegerScaling;
extern int ScreenFilter; extern int ScreenFilter;

View File

@ -646,15 +646,25 @@ void ScreenHandler::screenSetupLayout(int w, int h)
int sizing = Config::ScreenSizing; int sizing = Config::ScreenSizing;
if (sizing == 3) sizing = autoScreenSizing; 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, Frontend::SetupScreenLayout(w, h,
Config::ScreenLayout, Config::ScreenLayout,
Config::ScreenRotation, Config::ScreenRotation,
sizing, sizing,
Config::ScreenGap, Config::ScreenGap,
Config::IntegerScaling != 0, 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() QSize ScreenHandler::screenGetMinSize()
@ -779,19 +789,16 @@ void ScreenPanelNative::setupScreenLayout()
{ {
int w = width(); int w = width();
int h = height(); int h = height();
float* mtx;
screenSetupLayout(w, h); screenSetupLayout(w, h);
mtx = screenMatrix[0]; for (int i = 0; i < numScreens; i++)
screenTrans[0].setMatrix(mtx[0], mtx[1], 0.f, {
mtx[2], mtx[3], 0.f, float* mtx = screenMatrix[i];
mtx[4], mtx[5], 1.f); screenTrans[i].setMatrix(mtx[0], mtx[1], 0.f,
mtx[2], mtx[3], 0.f,
mtx = screenMatrix[1]; mtx[4], mtx[5], 1.f);
screenTrans[1].setMatrix(mtx[0], mtx[1], 0.f, }
mtx[2], mtx[3], 0.f,
mtx[4], mtx[5], 1.f);
} }
void ScreenPanelNative::paintEvent(QPaintEvent* event) void ScreenPanelNative::paintEvent(QPaintEvent* event)
@ -811,11 +818,11 @@ void ScreenPanelNative::paintEvent(QPaintEvent* event)
QRect screenrc(0, 0, 256, 192); QRect screenrc(0, 0, 256, 192);
painter.setTransform(screenTrans[0]); for (int i = 0; i < numScreens; i++)
painter.drawImage(screenrc, screen[0]); {
painter.setTransform(screenTrans[i]);
painter.setTransform(screenTrans[1]); painter.drawImage(screenrc, screen[screenKind[i]]);
painter.drawImage(screenrc, screen[1]); }
OSD::Update(nullptr); OSD::Update(nullptr);
OSD::DrawNative(painter); OSD::DrawNative(painter);
@ -1002,11 +1009,11 @@ void ScreenPanelGL::paintGL()
GLint transloc = screenShader->uniformLocation("uTransform"); GLint transloc = screenShader->uniformLocation("uTransform");
glUniformMatrix2x3fv(transloc, 1, GL_TRUE, screenMatrix[0]); for (int i = 0; i < numScreens; i++)
glDrawArrays(GL_TRIANGLES, 0, 2*3); {
glUniformMatrix2x3fv(transloc, 1, GL_TRUE, screenMatrix[i]);
glUniformMatrix2x3fv(transloc, 1, GL_TRUE, screenMatrix[1]); glDrawArrays(GL_TRIANGLES, screenKind[i] == 0 ? 0 : 2*3, 2*3);
glDrawArrays(GL_TRIANGLES, 2*3, 2*3); }
screenShader->release(); screenShader->release();
@ -1272,9 +1279,9 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
QMenu* submenu = menu->addMenu("Screen sizing"); QMenu* submenu = menu->addMenu("Screen sizing");
grpScreenSizing = new QActionGroup(submenu); 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] = submenu->addAction(QString(screensizing[i]));
actScreenSizing[i]->setActionGroup(grpScreenSizing); actScreenSizing[i]->setActionGroup(grpScreenSizing);
@ -1290,6 +1297,38 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actIntegerScaling->setCheckable(true); actIntegerScaling->setCheckable(true);
connect(actIntegerScaling, &QAction::triggered, this, &MainWindow::onChangeIntegerScaling); 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 = menu->addAction("Screen filtering");
actScreenFiltering->setCheckable(true); actScreenFiltering->setCheckable(true);
@ -1352,6 +1391,9 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actScreenSwap->setChecked(Config::ScreenSwap != 0); actScreenSwap->setChecked(Config::ScreenSwap != 0);
actScreenAspectTop[Config::ScreenAspectTop]->setChecked(true);
actScreenAspectBot[Config::ScreenAspectBot]->setChecked(true);
actScreenFiltering->setChecked(Config::ScreenFilter != 0); actScreenFiltering->setChecked(Config::ScreenFilter != 0);
actShowOSD->setChecked(Config::ShowOSD != 0); actShowOSD->setChecked(Config::ShowOSD != 0);
@ -2264,6 +2306,22 @@ void MainWindow::onChangeScreenSizing(QAction* act)
emit screenLayoutChange(); 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) void MainWindow::onChangeIntegerScaling(bool checked)
{ {
Config::IntegerScaling = checked?1:0; Config::IntegerScaling = checked?1:0;
@ -2444,7 +2502,9 @@ int main(int argc, char** argv)
SANITIZE(Config::ScreenRotation, 0, 3); SANITIZE(Config::ScreenRotation, 0, 3);
SANITIZE(Config::ScreenGap, 0, 500); SANITIZE(Config::ScreenGap, 0, 500);
SANITIZE(Config::ScreenLayout, 0, 2); 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 #undef SANITIZE
QSurfaceFormat format; QSurfaceFormat format;

View File

@ -34,6 +34,7 @@
#include <QOpenGLFunctions_3_2_Core> #include <QOpenGLFunctions_3_2_Core>
#include <QOpenGLShaderProgram> #include <QOpenGLShaderProgram>
#include "FrontendUtil.h"
class EmuThread : public QThread class EmuThread : public QThread
{ {
@ -105,7 +106,9 @@ protected:
void screenOnMouseRelease(QMouseEvent* event); void screenOnMouseRelease(QMouseEvent* event);
void screenOnMouseMove(QMouseEvent* event); void screenOnMouseMove(QMouseEvent* event);
float screenMatrix[2][6]; float screenMatrix[Frontend::MaxScreenTransforms][6];
int screenKind[Frontend::MaxScreenTransforms];
int numScreens;
bool touching; bool touching;
@ -137,7 +140,7 @@ private:
void setupScreenLayout(); void setupScreenLayout();
QImage screen[2]; QImage screen[2];
QTransform screenTrans[2]; QTransform screenTrans[Frontend::MaxScreenTransforms];
}; };
@ -237,6 +240,8 @@ private slots:
void onChangeScreenLayout(QAction* act); void onChangeScreenLayout(QAction* act);
void onChangeScreenSwap(bool checked); void onChangeScreenSwap(bool checked);
void onChangeScreenSizing(QAction* act); void onChangeScreenSizing(QAction* act);
void onChangeScreenAspectTop(QAction* act);
void onChangeScreenAspectBot(QAction* act);
void onChangeIntegerScaling(bool checked); void onChangeIntegerScaling(bool checked);
void onChangeScreenFiltering(bool checked); void onChangeScreenFiltering(bool checked);
void onChangeShowOSD(bool checked); void onChangeShowOSD(bool checked);
@ -303,8 +308,12 @@ public:
QAction* actScreenLayout[3]; QAction* actScreenLayout[3];
QAction* actScreenSwap; QAction* actScreenSwap;
QActionGroup* grpScreenSizing; QActionGroup* grpScreenSizing;
QAction* actScreenSizing[4]; QAction* actScreenSizing[6];
QAction* actIntegerScaling; QAction* actIntegerScaling;
QActionGroup* grpScreenAspectTop;
QAction* actScreenAspectTop[4];
QActionGroup* grpScreenAspectBot;
QAction* actScreenAspectBot[4];
QAction* actScreenFiltering; QAction* actScreenFiltering;
QAction* actShowOSD; QAction* actShowOSD;
QAction* actLimitFramerate; QAction* actLimitFramerate;