mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 15:45:38 +00:00
Added support for rotating the application screen contents 0, 90, 180 or 270 degrees.
Also improved post processing shader rendering when running in vertical orientation.
This commit is contained in:
parent
b3c997600c
commit
b33c7603bb
|
@ -71,21 +71,21 @@ void MediaViewer::render(const glm::mat4& /*parentTrans*/)
|
|||
shaders = Renderer::Shader::SCANLINES;
|
||||
if (Settings::getInstance()->getBool("MediaViewerVideoBlur")) {
|
||||
shaders |= Renderer::Shader::BLUR_HORIZONTAL;
|
||||
float heightModifier {Renderer::getScreenHeightModifier()};
|
||||
const float resolutionModifier {mRenderer->getScreenResolutionModifier()};
|
||||
// clang-format off
|
||||
if (heightModifier < 1)
|
||||
if (resolutionModifier < 1)
|
||||
videoParameters.blurPasses = 2; // Below 1080
|
||||
else if (heightModifier >= 4)
|
||||
else if (resolutionModifier >= 4)
|
||||
videoParameters.blurPasses = 12; // 8K
|
||||
else if (heightModifier >= 2.9)
|
||||
else if (resolutionModifier >= 2.9)
|
||||
videoParameters.blurPasses = 10; // 6K
|
||||
else if (heightModifier >= 2.6)
|
||||
else if (resolutionModifier >= 2.6)
|
||||
videoParameters.blurPasses = 8; // 5K
|
||||
else if (heightModifier >= 2)
|
||||
else if (resolutionModifier >= 2)
|
||||
videoParameters.blurPasses = 5; // 4K
|
||||
else if (heightModifier >= 1.3)
|
||||
else if (resolutionModifier >= 1.3)
|
||||
videoParameters.blurPasses = 3; // 1440
|
||||
else if (heightModifier >= 1)
|
||||
else if (resolutionModifier >= 1)
|
||||
videoParameters.blurPasses = 2; // 1080
|
||||
// clang-format on
|
||||
}
|
||||
|
|
|
@ -327,21 +327,21 @@ void Screensaver::renderScreensaver()
|
|||
shaders = Renderer::Shader::SCANLINES;
|
||||
if (Settings::getInstance()->getBool("ScreensaverVideoBlur")) {
|
||||
shaders |= Renderer::Shader::BLUR_HORIZONTAL;
|
||||
float heightModifier {Renderer::getScreenHeightModifier()};
|
||||
const float resolutionModifier {mRenderer->getScreenResolutionModifier()};
|
||||
// clang-format off
|
||||
if (heightModifier < 1)
|
||||
if (resolutionModifier < 1)
|
||||
videoParameters.blurPasses = 2; // Below 1080
|
||||
else if (heightModifier >= 4)
|
||||
else if (resolutionModifier >= 4)
|
||||
videoParameters.blurPasses = 12; // 8K
|
||||
else if (heightModifier >= 2.9)
|
||||
else if (resolutionModifier >= 2.9)
|
||||
videoParameters.blurPasses = 10; // 6K
|
||||
else if (heightModifier >= 2.6)
|
||||
else if (resolutionModifier >= 2.6)
|
||||
videoParameters.blurPasses = 8; // 5K
|
||||
else if (heightModifier >= 2)
|
||||
else if (resolutionModifier >= 2)
|
||||
videoParameters.blurPasses = 5; // 4K
|
||||
else if (heightModifier >= 1.3)
|
||||
else if (resolutionModifier >= 1.3)
|
||||
videoParameters.blurPasses = 3; // 1440
|
||||
else if (heightModifier >= 1)
|
||||
else if (resolutionModifier >= 1)
|
||||
videoParameters.blurPasses = 2; // 1080
|
||||
// clang-format on
|
||||
}
|
||||
|
|
|
@ -1303,6 +1303,29 @@ void GuiMenu::openOtherOptions()
|
|||
}
|
||||
});
|
||||
|
||||
// Screen contents rotation.
|
||||
auto screenRotate =
|
||||
std::make_shared<OptionListComponent<std::string>>(getHelpStyle(), "ROTATE SCREEN", false);
|
||||
const std::string& selectedScreenRotate {
|
||||
std::to_string(Settings::getInstance()->getInt("ScreenRotate"))};
|
||||
screenRotate->add("DISABLED", "0", selectedScreenRotate == "0");
|
||||
screenRotate->add("90 DEGREES", "90", selectedScreenRotate == "90");
|
||||
screenRotate->add("180 DEGREES", "180", selectedScreenRotate == "180");
|
||||
screenRotate->add("270 DEGREES", "270", selectedScreenRotate == "270");
|
||||
// If there are no objects returned, then there must be a manually modified entry in the
|
||||
// configuration file. Simply set screen rotation to "0" in this case.
|
||||
if (screenRotate->getSelectedObjects().size() == 0)
|
||||
screenRotate->selectEntry(0);
|
||||
s->addWithLabel("ROTATE SCREEN (REQUIRES RESTART)", screenRotate);
|
||||
s->addSaveFunc([screenRotate, s] {
|
||||
if (screenRotate->getSelected() !=
|
||||
std::to_string(Settings::getInstance()->getInt("ScreenRotate"))) {
|
||||
Settings::getInstance()->setInt("ScreenRotate",
|
||||
atoi(screenRotate->getSelected().c_str()));
|
||||
s->setNeedsSaving();
|
||||
}
|
||||
});
|
||||
|
||||
// Keyboard quit shortcut.
|
||||
auto keyboardQuitShortcut = std::make_shared<OptionListComponent<std::string>>(
|
||||
getHelpStyle(), "KEYBOARD QUIT SHORTCUT", false);
|
||||
|
|
|
@ -297,14 +297,14 @@ bool parseArgs(int argc, char* argv[])
|
|||
std::cerr << "Error: No screenrotate value supplied\n";
|
||||
return false;
|
||||
}
|
||||
std::string rotateValue {argv[i + 1]};
|
||||
if (rotateValue != "on" && rotateValue != "off" && rotateValue != "1" &&
|
||||
rotateValue != "0") {
|
||||
const std::string rotateValue {argv[i + 1]};
|
||||
if (rotateValue != "0" && rotateValue != "90" && rotateValue != "180" &&
|
||||
rotateValue != "270") {
|
||||
std::cerr << "Error: Invalid screenrotate value supplied\n";
|
||||
return false;
|
||||
}
|
||||
bool screenRotate {(rotateValue == "on" || rotateValue == "1") ? true : false};
|
||||
Settings::getInstance()->setBool("ScreenRotate", screenRotate);
|
||||
Settings::getInstance()->setInt("ScreenRotate", atoi(argv[i + 1]));
|
||||
settingsNeedSaving = true;
|
||||
++i;
|
||||
}
|
||||
else if (strcmp(argv[i], "--vsync") == 0) {
|
||||
|
@ -401,28 +401,28 @@ bool parseArgs(int argc, char* argv[])
|
|||
"Usage: emulationstation [options]\n"
|
||||
"EmulationStation Desktop Edition, Emulator Frontend\n\n"
|
||||
"Options:\n"
|
||||
" --display [index 1-4] Display/monitor to use\n"
|
||||
" --resolution [width] [height] Application resolution\n"
|
||||
" --screenrotate [1/on or 0/off] Rotate application screen 180 degrees\n"
|
||||
" --vsync [1/on or 0/off] Turn VSync on or off (default is on)\n"
|
||||
" --max-vram [size] Max VRAM to use (in mebibytes) before swapping\n"
|
||||
" --display [1 to 4] Display/monitor to use\n"
|
||||
" --resolution [width] [height] Application resolution\n"
|
||||
" --screenrotate [0, 90, 180 or 270] Rotate screen contents within application window\n"
|
||||
" --vsync [1/on or 0/off] Turn VSync on or off (default is on)\n"
|
||||
" --max-vram [size] Max VRAM to use (in mebibytes) before swapping\n"
|
||||
#if !defined(USE_OPENGLES)
|
||||
" --anti-aliasing [0, 2 or 4] Set MSAA anti-aliasing to disabled, 2x or 4x\n"
|
||||
" --anti-aliasing [0, 2 or 4] Set MSAA anti-aliasing to disabled, 2x or 4x\n"
|
||||
#endif
|
||||
" --no-splash Don't show the splash screen during startup\n"
|
||||
" --gamelist-only Skip automatic game ROM search, only read from gamelist.xml\n"
|
||||
" --ignore-gamelist Ignore the gamelist.xml files (useful for troubleshooting)\n"
|
||||
" --show-hidden-files Show hidden files and folders\n"
|
||||
" --show-hidden-games Show hidden games\n"
|
||||
" --force-full Force the UI mode to Full\n"
|
||||
" --force-kiosk Force the UI mode to Kiosk\n"
|
||||
" --force-kid Force the UI mode to Kid\n"
|
||||
" --force-input-config Force configuration of input device\n"
|
||||
" --create-system-dirs Create game system directories\n"
|
||||
" --home [path] Directory to use as home path\n"
|
||||
" --debug Print debug information\n"
|
||||
" --version, -v Display version information\n"
|
||||
" --help, -h Summon a sentient, angry tuba\n";
|
||||
" --no-splash Don't show the splash screen during startup\n"
|
||||
" --gamelist-only Skip automatic game ROM search, only read from gamelist.xml\n"
|
||||
" --ignore-gamelist Ignore the gamelist.xml files (useful for troubleshooting)\n"
|
||||
" --show-hidden-files Show hidden files and folders\n"
|
||||
" --show-hidden-games Show hidden games\n"
|
||||
" --force-full Force the UI mode to Full\n"
|
||||
" --force-kiosk Force the UI mode to Kiosk\n"
|
||||
" --force-kid Force the UI mode to Kid\n"
|
||||
" --force-input-config Force configuration of input devices\n"
|
||||
" --create-system-dirs Create game system directories\n"
|
||||
" --home [path] Directory to use as home path\n"
|
||||
" --debug Print debug information\n"
|
||||
" --version, -v Display version information\n"
|
||||
" --help, -h Summon a sentient, angry tuba\n";
|
||||
// clang-format on
|
||||
return false; // Exit after printing help.
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ namespace
|
|||
"IgnoreGamelist", // --ignore-gamelist
|
||||
"SplashScreen", // --no-splash
|
||||
"Debug", // --debug
|
||||
"ScreenRotate", // --screenrotate [1/on or 0/off]
|
||||
"VSync", // --vsync [1/on or 0/off]
|
||||
"ForceFull", // --force-full
|
||||
"ForceKiosk", // --force-kiosk
|
||||
|
@ -246,10 +245,11 @@ void Settings::setDefaults()
|
|||
#else
|
||||
mIntMap["MaxVRAM"] = {512, 512};
|
||||
#endif
|
||||
mIntMap["DisplayIndex"] = {1, 1};
|
||||
#if !defined(USE_OPENGLES)
|
||||
mIntMap["AntiAliasing"] = {0, 0};
|
||||
#endif
|
||||
mIntMap["DisplayIndex"] = {1, 1};
|
||||
mIntMap["ScreenRotate"] = {0, 0};
|
||||
#if defined(__APPLE__)
|
||||
mStringMap["KeyboardQuitShortcut"] = {"CmdQ", "CmdQ"};
|
||||
#else
|
||||
|
@ -295,7 +295,6 @@ void Settings::setDefaults()
|
|||
mBoolMap["ForceKiosk"] = {false, false};
|
||||
mBoolMap["IgnoreGamelist"] = {false, false};
|
||||
mBoolMap["SplashScreen"] = {true, true};
|
||||
mBoolMap["ScreenRotate"] = {false, false};
|
||||
mBoolMap["VSync"] = {true, true};
|
||||
mIntMap["WindowWidth"] = {0, 0};
|
||||
mIntMap["WindowHeight"] = {0, 0};
|
||||
|
|
|
@ -160,7 +160,7 @@ bool Window::init()
|
|||
progressBarRect.color = DEFAULT_TEXTCOLOR;
|
||||
mProgressBarRectangles.emplace_back(progressBarRect);
|
||||
|
||||
const float borderThickness {std::ceil(2.0f * mRenderer->getScreenHeightModifier())};
|
||||
const float borderThickness {std::ceil(2.0f * mRenderer->getScreenResolutionModifier())};
|
||||
|
||||
progressBarRect.barWidth -= borderThickness * 2.0f;
|
||||
progressBarRect.barHeight -= borderThickness * 2.0f;
|
||||
|
@ -502,21 +502,21 @@ void Window::render()
|
|||
Renderer::postProcessingParams backgroundParameters;
|
||||
|
||||
if (Settings::getInstance()->getBool("MenuBlurBackground")) {
|
||||
float heightModifier {mRenderer->getScreenHeightModifier()};
|
||||
const float resolutionModifier {mRenderer->getScreenResolutionModifier()};
|
||||
// clang-format off
|
||||
if (heightModifier < 1)
|
||||
if (resolutionModifier < 1)
|
||||
backgroundParameters.blurPasses = 2; // Below 1080
|
||||
else if (heightModifier >= 4)
|
||||
else if (resolutionModifier >= 4)
|
||||
backgroundParameters.blurPasses = 12; // 8K
|
||||
else if (heightModifier >= 2.9)
|
||||
else if (resolutionModifier >= 2.9)
|
||||
backgroundParameters.blurPasses = 10; // 6K
|
||||
else if (heightModifier >= 2.6)
|
||||
else if (resolutionModifier >= 2.6)
|
||||
backgroundParameters.blurPasses = 8; // 5K
|
||||
else if (heightModifier >= 2)
|
||||
else if (resolutionModifier >= 2)
|
||||
backgroundParameters.blurPasses = 5; // 4K
|
||||
else if (heightModifier >= 1.3)
|
||||
else if (resolutionModifier >= 1.3)
|
||||
backgroundParameters.blurPasses = 3; // 1440
|
||||
else if (heightModifier >= 1)
|
||||
else if (resolutionModifier >= 1)
|
||||
backgroundParameters.blurPasses = 2; // 1080
|
||||
// clang-format on
|
||||
|
||||
|
@ -535,9 +535,16 @@ void Window::render()
|
|||
&processedTexture[0]);
|
||||
}
|
||||
|
||||
mPostprocessedBackground->initFromPixels(
|
||||
&processedTexture[0], static_cast<size_t>(mRenderer->getScreenWidth()),
|
||||
static_cast<size_t>(mRenderer->getScreenHeight()));
|
||||
if (mRenderer->getScreenRotation() == 0 || mRenderer->getScreenRotation() == 180) {
|
||||
mPostprocessedBackground->initFromPixels(
|
||||
&processedTexture[0], static_cast<size_t>(mRenderer->getScreenWidth()),
|
||||
static_cast<size_t>(mRenderer->getScreenHeight()));
|
||||
}
|
||||
else {
|
||||
mPostprocessedBackground->initFromPixels(
|
||||
&processedTexture[0], static_cast<size_t>(mRenderer->getScreenHeight()),
|
||||
static_cast<size_t>(mRenderer->getScreenWidth()));
|
||||
}
|
||||
|
||||
mBackgroundOverlay->setImage(mPostprocessedBackground);
|
||||
|
||||
|
|
|
@ -119,7 +119,30 @@ bool Renderer::createWindow()
|
|||
mScreenOffsetY = Settings::getInstance()->getInt("ScreenOffsetY") ?
|
||||
Settings::getInstance()->getInt("ScreenOffsetY") :
|
||||
0;
|
||||
mScreenRotated = Settings::getInstance()->getBool("ScreenRotate");
|
||||
mScreenRotation = Settings::getInstance()->getInt("ScreenRotate");
|
||||
|
||||
// In case someone manually added an invalid value to es_settings.xml.
|
||||
if (mScreenRotation != 0 && mScreenRotation != 90 && mScreenRotation != 180 &&
|
||||
mScreenRotation != 270) {
|
||||
LOG(LogWarning) << "Invalid screen rotation value " << mScreenRotation
|
||||
<< " defined, changing it to 0/disabled";
|
||||
mScreenRotation = 0;
|
||||
}
|
||||
|
||||
LOG(LogInfo) << "Screen rotation: "
|
||||
<< (mScreenRotation == 0 ? "disabled" :
|
||||
std::to_string(mScreenRotation) + " degrees");
|
||||
|
||||
if (mScreenRotation == 90 || mScreenRotation == 270) {
|
||||
const int tempVal {sScreenWidth};
|
||||
sScreenWidth = sScreenHeight;
|
||||
sScreenHeight = tempVal;
|
||||
}
|
||||
|
||||
if (sScreenHeight > sScreenWidth)
|
||||
sIsVerticalOrientation = true;
|
||||
else
|
||||
sIsVerticalOrientation = false;
|
||||
|
||||
// Prevent the application window from minimizing when switching windows (when launching
|
||||
// games or when manually switching windows using the task switcher).
|
||||
|
@ -224,6 +247,11 @@ bool Renderer::createWindow()
|
|||
sScreenWidthModifier = static_cast<float>(sScreenWidth) / 1920.0f;
|
||||
sScreenAspectRatio = static_cast<float>(sScreenWidth) / static_cast<float>(sScreenHeight);
|
||||
|
||||
if (sIsVerticalOrientation)
|
||||
sScreenResolutionModifier = sScreenWidth / 1080.0f;
|
||||
else
|
||||
sScreenResolutionModifier = sScreenHeight / 1080.0f;
|
||||
|
||||
LOG(LogInfo) << "Setting up OpenGL...";
|
||||
|
||||
if (!createContext())
|
||||
|
@ -265,18 +293,41 @@ bool Renderer::init()
|
|||
viewport.y = mWindowHeight - mScreenOffsetY - sScreenHeight;
|
||||
viewport.w = sScreenWidth;
|
||||
viewport.h = sScreenHeight;
|
||||
projection = glm::ortho(0.0f, static_cast<float>(sScreenWidth),
|
||||
static_cast<float>(sScreenHeight), 0.0f, -1.0f, 1.0f);
|
||||
projection = glm::rotate(projection, glm::radians(180.0f), {0.0f, 0.0f, 1.0f});
|
||||
mProjectionMatrixRotated =
|
||||
glm::translate(projection, {sScreenWidth * -1.0f, sScreenHeight * -1.0f, 0.0f});
|
||||
|
||||
projection = glm::ortho(0.0f, static_cast<float>(sScreenHeight),
|
||||
static_cast<float>(sScreenWidth), 0.0f, -1.0f, 1.0f);
|
||||
|
||||
if (mScreenRotation == 0) {
|
||||
mProjectionMatrix = glm::ortho(0.0f, static_cast<float>(sScreenWidth),
|
||||
static_cast<float>(sScreenHeight), 0.0f, -1.0f, 1.0f);
|
||||
}
|
||||
else if (mScreenRotation == 90) {
|
||||
projection = glm::ortho(0.0f, static_cast<float>(sScreenHeight),
|
||||
static_cast<float>(sScreenWidth), 0.0f, -1.0f, 1.0f);
|
||||
projection = glm::rotate(projection, glm::radians(90.0f), {0.0f, 0.0f, 1.0f});
|
||||
mProjectionMatrix = glm::translate(projection, {0.0f, sScreenHeight * -1.0f, 0.0f});
|
||||
}
|
||||
else if (mScreenRotation == 180) {
|
||||
projection = glm::ortho(0.0f, static_cast<float>(sScreenWidth),
|
||||
static_cast<float>(sScreenHeight), 0.0f, -1.0f, 1.0f);
|
||||
projection = glm::rotate(projection, glm::radians(180.0f), {0.0f, 0.0f, 1.0f});
|
||||
mProjectionMatrix =
|
||||
glm::translate(projection, {sScreenWidth * -1.0f, sScreenHeight * -1.0f, 0.0f});
|
||||
}
|
||||
else if (mScreenRotation == 270) {
|
||||
projection = glm::ortho(0.0f, static_cast<float>(sScreenHeight),
|
||||
static_cast<float>(sScreenWidth), 0.0f, -1.0f, 1.0f);
|
||||
projection = glm::rotate(projection, glm::radians(270.0f), {0.0f, 0.0f, 1.0f});
|
||||
mProjectionMatrix = glm::translate(projection, {sScreenWidth * -1.0f, 0.0f, 0.0f});
|
||||
}
|
||||
|
||||
mProjectionMatrixNormal = glm::ortho(0.0f, static_cast<float>(sScreenWidth),
|
||||
static_cast<float>(sScreenHeight), 0.0f, -1.0f, 1.0f);
|
||||
|
||||
viewport.x = mScreenOffsetX;
|
||||
viewport.y = mScreenOffsetY;
|
||||
viewport.w = sScreenWidth;
|
||||
viewport.h = sScreenHeight;
|
||||
mProjectionMatrix = glm::ortho(0.0f, static_cast<float>(sScreenWidth),
|
||||
static_cast<float>(sScreenHeight), 0.0f, -1.0f, 1.0f);
|
||||
|
||||
// This is required to avoid a brief white screen flash during startup on some systems.
|
||||
drawRect(0.0f, 0.0f, static_cast<float>(getScreenWidth()),
|
||||
|
@ -301,12 +352,20 @@ void Renderer::pushClipRect(const glm::ivec2& pos, const glm::ivec2& size)
|
|||
if (box.h == 0)
|
||||
box.h = sScreenHeight - box.y;
|
||||
|
||||
if (mScreenRotated) {
|
||||
box = Rect {mWindowWidth - mScreenOffsetX - box.x - box.w,
|
||||
mWindowHeight - mScreenOffsetY - box.y - box.h, box.w, box.h};
|
||||
if (mScreenRotation == 0) {
|
||||
box = {mScreenOffsetX + box.x, mScreenOffsetY + box.y, box.w, box.h};
|
||||
}
|
||||
else {
|
||||
box = Rect {mScreenOffsetX + box.x, mScreenOffsetY + box.y, box.w, box.h};
|
||||
else if (mScreenRotation == 90) {
|
||||
box = {mScreenOffsetX + mWindowWidth - (box.y + box.h), mScreenOffsetY + box.x, box.h,
|
||||
box.w};
|
||||
}
|
||||
else if (mScreenRotation == 270) {
|
||||
box = {mScreenOffsetX + box.y, mScreenOffsetY + mWindowHeight - (box.x + box.w), box.h,
|
||||
box.w};
|
||||
}
|
||||
else if (mScreenRotation == 180) {
|
||||
box = {mWindowWidth - mScreenOffsetX - box.x - box.w,
|
||||
mWindowHeight - mScreenOffsetY - box.y - box.h, box.w, box.h};
|
||||
}
|
||||
|
||||
// Make sure the box fits within mClipStack.top(), and clip further accordingly.
|
||||
|
@ -328,7 +387,6 @@ void Renderer::pushClipRect(const glm::ivec2& pos, const glm::ivec2& size)
|
|||
box.h = 0;
|
||||
|
||||
mClipStack.push(box);
|
||||
|
||||
setScissor(box);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,8 @@ public:
|
|||
PREMULTIPLIED = 0x00000001,
|
||||
FONT_TEXTURE = 0x00000002,
|
||||
POST_PROCESSING = 0x00000004,
|
||||
CLIPPING = 0x00000008
|
||||
CLIPPING = 0x00000008,
|
||||
ROTATED = 0x00000010 // Screen rotated 90 or 270 degrees.
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
@ -155,16 +156,11 @@ public:
|
|||
const BlendFactor srcBlendFactor = BlendFactor::SRC_ALPHA,
|
||||
const BlendFactor dstBlendFactor = BlendFactor::ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
const glm::mat4& getProjectionMatrix()
|
||||
{
|
||||
if (mScreenRotated)
|
||||
return mProjectionMatrixRotated;
|
||||
else
|
||||
return mProjectionMatrix;
|
||||
}
|
||||
const glm::mat4& getProjectionMatrixNormal() { return mProjectionMatrix; }
|
||||
const glm::mat4& getProjectionMatrix() { return mProjectionMatrix; }
|
||||
const glm::mat4& getProjectionMatrixNormal() { return mProjectionMatrixNormal; }
|
||||
SDL_Window* getSDLWindow() { return mSDLWindow; }
|
||||
const bool getScreenRotated() { return mScreenRotated; }
|
||||
const int getScreenRotation() { return mScreenRotation; }
|
||||
const bool getIsVerticalOrientation() { return sIsVerticalOrientation; }
|
||||
const float getWindowWidth() { return static_cast<float>(mWindowWidth); }
|
||||
const float getWindowHeight() { return static_cast<float>(mWindowHeight); }
|
||||
static const float getScreenWidth() { return static_cast<float>(sScreenWidth); }
|
||||
|
@ -172,6 +168,7 @@ public:
|
|||
static const float getScreenWidthModifier() { return sScreenWidthModifier; }
|
||||
static const float getScreenHeightModifier() { return sScreenHeightModifier; }
|
||||
static const float getScreenAspectRatio() { return sScreenAspectRatio; }
|
||||
static const float getScreenResolutionModifier() { return sScreenResolutionModifier; }
|
||||
|
||||
static constexpr glm::mat4 getIdentity() { return glm::mat4 {1.0f}; }
|
||||
glm::mat4 mTrans {getIdentity()};
|
||||
|
@ -215,19 +212,21 @@ private:
|
|||
std::stack<Rect> mClipStack;
|
||||
SDL_Window* mSDLWindow {nullptr};
|
||||
glm::mat4 mProjectionMatrix {};
|
||||
glm::mat4 mProjectionMatrixRotated {};
|
||||
glm::mat4 mProjectionMatrixNormal {};
|
||||
int mWindowWidth {0};
|
||||
int mWindowHeight {0};
|
||||
static inline int sScreenWidth {0};
|
||||
static inline int sScreenHeight {0};
|
||||
int mScreenOffsetX {0};
|
||||
int mScreenOffsetY {0};
|
||||
bool mScreenRotated {0};
|
||||
bool mInitialCursorState {1};
|
||||
int mScreenRotation {0};
|
||||
bool mInitialCursorState {true};
|
||||
static inline bool sIsVerticalOrientation {false};
|
||||
// Screen resolution modifiers relative to the 1920x1080 reference.
|
||||
static inline float sScreenHeightModifier {0.0f};
|
||||
static inline float sScreenWidthModifier {0.0f};
|
||||
static inline float sScreenAspectRatio {0.0f};
|
||||
static inline float sScreenResolutionModifier {0.0f};
|
||||
};
|
||||
|
||||
#endif // ES_CORE_RENDERER_RENDERER_H
|
||||
|
|
|
@ -269,13 +269,22 @@ bool RendererOpenGL::createContext()
|
|||
uint8_t data[4] {255, 255, 255, 255};
|
||||
mWhiteTexture = createTexture(TextureType::BGRA, false, false, false, true, 1, 1, data);
|
||||
|
||||
mPostProcTexture1 = createTexture(TextureType::BGRA, false, false, false, false,
|
||||
static_cast<unsigned int>(getScreenWidth()),
|
||||
static_cast<unsigned int>(getScreenHeight()), nullptr);
|
||||
unsigned int textureWidth {0};
|
||||
unsigned int textureHeight {0};
|
||||
|
||||
mPostProcTexture2 = createTexture(TextureType::BGRA, false, false, false, false,
|
||||
static_cast<unsigned int>(getScreenWidth()),
|
||||
static_cast<unsigned int>(getScreenHeight()), nullptr);
|
||||
if (getScreenRotation() == 0 || getScreenRotation() == 180) {
|
||||
textureWidth = static_cast<unsigned int>(getScreenWidth());
|
||||
textureHeight = static_cast<unsigned int>(getScreenHeight());
|
||||
}
|
||||
else {
|
||||
textureWidth = static_cast<unsigned int>(getScreenHeight());
|
||||
textureHeight = static_cast<unsigned int>(getScreenWidth());
|
||||
}
|
||||
|
||||
mPostProcTexture1 = createTexture(TextureType::BGRA, false, false, false, false, textureWidth,
|
||||
textureHeight, nullptr);
|
||||
mPostProcTexture2 = createTexture(TextureType::BGRA, false, false, false, false, textureWidth,
|
||||
textureHeight, nullptr);
|
||||
|
||||
// Attach textures to the shader framebuffers.
|
||||
GL_CHECK_ERROR(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mShaderFBO1));
|
||||
|
@ -494,6 +503,7 @@ void RendererOpenGL::drawTriangleStrips(const Vertex* vertices,
|
|||
GL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * numVertices, vertices,
|
||||
GL_DYNAMIC_DRAW));
|
||||
mBlurHorizontalShader->setTextureSize({width, height});
|
||||
mBlurHorizontalShader->setFlags(vertices->shaderFlags);
|
||||
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices));
|
||||
mLastShader = mBlurHorizontalShader;
|
||||
}
|
||||
|
@ -511,6 +521,7 @@ void RendererOpenGL::drawTriangleStrips(const Vertex* vertices,
|
|||
GL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * numVertices, vertices,
|
||||
GL_DYNAMIC_DRAW));
|
||||
mBlurVerticalShader->setTextureSize({width, height});
|
||||
mBlurVerticalShader->setFlags(vertices->shaderFlags);
|
||||
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices));
|
||||
mLastShader = mBlurVerticalShader;
|
||||
}
|
||||
|
@ -521,12 +532,12 @@ void RendererOpenGL::drawTriangleStrips(const Vertex* vertices,
|
|||
mScanlinelShader = getShaderProgram(Shader::SCANLINES);
|
||||
float shaderWidth {width * 1.2f};
|
||||
// Scale the scanlines relative to screen resolution.
|
||||
float screenHeightModifier {getScreenHeightModifier()};
|
||||
float resolutionModifier {getScreenResolutionModifier()};
|
||||
float relativeHeight {height / getScreenHeight()};
|
||||
float shaderHeight {0.0f};
|
||||
if (relativeHeight == 1.0f) {
|
||||
// Full screen.
|
||||
float modifier {1.30f - (0.1f * screenHeightModifier)};
|
||||
float modifier {1.30f - (0.1f * resolutionModifier)};
|
||||
shaderHeight = height * modifier;
|
||||
}
|
||||
else {
|
||||
|
@ -535,7 +546,7 @@ void RendererOpenGL::drawTriangleStrips(const Vertex* vertices,
|
|||
// scanlines to videos with non-standard aspect ratios.
|
||||
float relativeWidth {width / getScreenWidth()};
|
||||
float relativeAdjustment {(relativeWidth + relativeHeight) / 2.0f};
|
||||
float modifier {1.41f + relativeAdjustment / 7.0f - (0.14f * screenHeightModifier)};
|
||||
float modifier {1.41f + relativeAdjustment / 7.0f - (0.14f * resolutionModifier)};
|
||||
shaderHeight = height * modifier;
|
||||
}
|
||||
if (mScanlinelShader) {
|
||||
|
@ -550,6 +561,7 @@ void RendererOpenGL::drawTriangleStrips(const Vertex* vertices,
|
|||
mScanlinelShader->setBrightness(vertices->brightness);
|
||||
mScanlinelShader->setSaturation(vertices->saturation);
|
||||
mScanlinelShader->setTextureSize({shaderWidth, shaderHeight});
|
||||
mScanlinelShader->setFlags(vertices->shaderFlags);
|
||||
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices));
|
||||
mLastShader = mScanlinelShader;
|
||||
}
|
||||
|
@ -566,6 +578,7 @@ void RendererOpenGL::shaderPostprocessing(unsigned int shaders,
|
|||
float heightf {getScreenHeight()};
|
||||
GLuint width {static_cast<GLuint>(widthf)};
|
||||
GLuint height {static_cast<GLuint>(heightf)};
|
||||
const int screenRotation {getScreenRotation()};
|
||||
|
||||
// Set vertex positions and texture coordinates to full screen as all
|
||||
// post-processing is applied to the complete screen area.
|
||||
|
@ -581,6 +594,9 @@ void RendererOpenGL::shaderPostprocessing(unsigned int shaders,
|
|||
vertices->dimming = parameters.dimming;
|
||||
vertices->shaderFlags = ShaderFlags::POST_PROCESSING | ShaderFlags::PREMULTIPLIED;
|
||||
|
||||
if (screenRotation == 90 || screenRotation == 270)
|
||||
vertices->shaderFlags |= ShaderFlags::ROTATED;
|
||||
|
||||
if (shaders & Shader::CORE)
|
||||
shaderList.push_back(Shader::CORE);
|
||||
if (shaders & Shader::BLUR_HORIZONTAL)
|
||||
|
@ -595,16 +611,52 @@ void RendererOpenGL::shaderPostprocessing(unsigned int shaders,
|
|||
|
||||
GL_CHECK_ERROR(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mShaderFBO1));
|
||||
|
||||
// Blit the screen contents to mPostProcTexture.
|
||||
GL_CHECK_ERROR(glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT,
|
||||
GL_NEAREST));
|
||||
int shaderCalls {0};
|
||||
bool evenBlurPasses {true};
|
||||
|
||||
GL_CHECK_ERROR(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mShaderFBO2));
|
||||
for (size_t i {0}; i < shaderList.size(); ++i) {
|
||||
if (shaderList[i] == Renderer::Shader::BLUR_HORIZONTAL ||
|
||||
shaderList[i] == Renderer::Shader::BLUR_VERTICAL) {
|
||||
shaderCalls += parameters.blurPasses;
|
||||
if (parameters.blurPasses % 2 != 0)
|
||||
evenBlurPasses = false;
|
||||
}
|
||||
else {
|
||||
++shaderCalls;
|
||||
}
|
||||
}
|
||||
|
||||
// Blit the screen contents to mPostProcTexture.
|
||||
if (screenRotation == 0) {
|
||||
GL_CHECK_ERROR(glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST));
|
||||
}
|
||||
else if (screenRotation == 90 || screenRotation == 270) {
|
||||
if (!evenBlurPasses || !textureRGBA)
|
||||
GL_CHECK_ERROR(glBlitFramebuffer(0, 0, height, width, 0, 0, height, width,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST));
|
||||
else
|
||||
GL_CHECK_ERROR(glBlitFramebuffer(0, 0, height, width, height, width, 0, 0,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST));
|
||||
// If not rendering to a texture, apply shaders without any rotation applied.
|
||||
if (!textureRGBA)
|
||||
mTrans = getProjectionMatrixNormal() * getIdentity();
|
||||
}
|
||||
else {
|
||||
if ((shaderCalls + (textureRGBA ? 1 : 0)) % 2 == 0)
|
||||
GL_CHECK_ERROR(glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST));
|
||||
else
|
||||
GL_CHECK_ERROR(glBlitFramebuffer(0, 0, width, height, width, height, 0, 0,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST));
|
||||
}
|
||||
|
||||
if (shaderCalls > 1)
|
||||
GL_CHECK_ERROR(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mShaderFBO2));
|
||||
|
||||
bool firstFBO {true};
|
||||
int drawCalls {0};
|
||||
|
||||
for (size_t i = 0; i < shaderList.size(); ++i) {
|
||||
for (size_t i {0}; i < shaderList.size(); ++i) {
|
||||
vertices->shaders = shaderList[i];
|
||||
int shaderPasses {1};
|
||||
// For the blur shaders there is an optional variable to set the number of passes
|
||||
|
@ -614,27 +666,17 @@ void RendererOpenGL::shaderPostprocessing(unsigned int shaders,
|
|||
shaderPasses = parameters.blurPasses;
|
||||
}
|
||||
|
||||
for (int p = 0; p < shaderPasses; ++p) {
|
||||
if (textureRGBA == nullptr && i == shaderList.size() - 1 && p == shaderPasses - 1) {
|
||||
// If the screen is rotated and we're at an even number of drawcalls, then
|
||||
// set the projection to a non-rotated state before making the last drawcall
|
||||
// as the image would otherwise get rendered upside down.
|
||||
if (getScreenRotated() && drawCalls % 2 == 0) {
|
||||
mTrans = getIdentity();
|
||||
mTrans[3] = glm::round(mTrans[3]);
|
||||
mTrans = getProjectionMatrixNormal() * mTrans;
|
||||
}
|
||||
// If it's the last shader pass, then render directly to the default framebuffer
|
||||
// to avoid having to make an expensive glBlitFramebuffer() call.
|
||||
for (int p {0}; p < shaderPasses; ++p) {
|
||||
if (!textureRGBA && i == shaderList.size() - 1 && p == shaderPasses - 1) {
|
||||
GL_CHECK_ERROR(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0));
|
||||
drawTriangleStrips(vertices, 4, BlendFactor::SRC_ALPHA,
|
||||
BlendFactor::ONE_MINUS_SRC_ALPHA);
|
||||
break;
|
||||
}
|
||||
// Apply/render the shaders.
|
||||
|
||||
drawTriangleStrips(vertices, 4, BlendFactor::SRC_ALPHA,
|
||||
BlendFactor::ONE_MINUS_SRC_ALPHA);
|
||||
++drawCalls;
|
||||
|
||||
if (firstFBO) {
|
||||
bindTexture(mPostProcTexture2);
|
||||
GL_CHECK_ERROR(glBindFramebuffer(GL_READ_FRAMEBUFFER, mShaderFBO2));
|
||||
|
@ -663,16 +705,22 @@ void RendererOpenGL::shaderPostprocessing(unsigned int shaders,
|
|||
GL_CHECK_ERROR(glBindFramebuffer(GL_READ_FRAMEBUFFER, mShaderFBO2));
|
||||
|
||||
#if defined(USE_OPENGLES)
|
||||
GL_CHECK_ERROR(
|
||||
glReadPixels(0, 0, width, height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, textureRGBA));
|
||||
if (screenRotation == 0 || screenRotation == 180)
|
||||
GL_CHECK_ERROR(
|
||||
glReadPixels(0, 0, width, height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, textureRGBA));
|
||||
else
|
||||
GL_CHECK_ERROR(
|
||||
glReadPixels(0, 0, height, width, GL_BGRA_EXT, GL_UNSIGNED_BYTE, textureRGBA));
|
||||
#else
|
||||
GL_CHECK_ERROR(glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, textureRGBA));
|
||||
if (screenRotation == 0 || screenRotation == 180)
|
||||
GL_CHECK_ERROR(
|
||||
glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, textureRGBA));
|
||||
else
|
||||
GL_CHECK_ERROR(
|
||||
glReadPixels(0, 0, height, width, GL_BGRA, GL_UNSIGNED_BYTE, textureRGBA));
|
||||
#endif
|
||||
GL_CHECK_ERROR(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0));
|
||||
}
|
||||
|
||||
if (getScreenRotated())
|
||||
setMatrix(getIdentity());
|
||||
|
||||
GL_CHECK_ERROR(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0));
|
||||
}
|
||||
|
|
|
@ -30,15 +30,28 @@ void main()
|
|||
precision mediump float;
|
||||
#endif
|
||||
|
||||
uniform uint shaderFlags;
|
||||
uniform vec2 textureSize;
|
||||
uniform sampler2D textureSampler;
|
||||
in vec2 texCoord;
|
||||
out vec4 FragColor;
|
||||
|
||||
#define SourceSize vec4(textureSize, 1.0 / textureSize)
|
||||
// shaderFlags:
|
||||
// 0x00000001 - Premultiplied alpha (BGRA)
|
||||
// 0x00000002 - Font texture
|
||||
// 0x00000004 - Post processing
|
||||
// 0x00000008 - Clipping
|
||||
// 0x00000010 - Screen rotated 90 or 270 degrees
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 SourceSize;
|
||||
|
||||
if (0x0u != (shaderFlags & 0x10u))
|
||||
SourceSize = vec4(textureSize.yx, 1.0 / textureSize.yx);
|
||||
else
|
||||
SourceSize = vec4(textureSize.xy, 1.0 / textureSize.xy);
|
||||
|
||||
vec2 PIXEL_SIZE = vec2(SourceSize.z, SourceSize.w);
|
||||
|
||||
float sampleOffsets[5] = float[5](0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130);
|
||||
|
|
|
@ -30,15 +30,28 @@ void main()
|
|||
precision mediump float;
|
||||
#endif
|
||||
|
||||
uniform uint shaderFlags;
|
||||
uniform vec2 textureSize;
|
||||
uniform sampler2D textureSampler;
|
||||
in vec2 texCoord;
|
||||
out vec4 FragColor;
|
||||
|
||||
#define SourceSize vec4(textureSize, 1.0 / textureSize)
|
||||
// shaderFlags:
|
||||
// 0x00000001 - Premultiplied alpha (BGRA)
|
||||
// 0x00000002 - Font texture
|
||||
// 0x00000004 - Post processing
|
||||
// 0x00000008 - Clipping
|
||||
// 0x00000010 - Screen rotated 90 or 270 degrees
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 SourceSize;
|
||||
|
||||
if (0x0u != (shaderFlags & 0x10u))
|
||||
SourceSize = vec4(textureSize.yx, 1.0 / textureSize.yx);
|
||||
else
|
||||
SourceSize = vec4(textureSize.xy, 1.0 / textureSize.xy);
|
||||
|
||||
vec2 PIXEL_SIZE = vec2(SourceSize.z, SourceSize.w);
|
||||
|
||||
float sampleOffsets[5] = float[5](0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130);
|
||||
|
|
|
@ -54,6 +54,7 @@ out vec4 FragColor;
|
|||
// 0x00000002 - Font texture
|
||||
// 0x00000004 - Post processing
|
||||
// 0x00000008 - Clipping
|
||||
// 0x00000010 - Screen rotated 90 or 270 degrees
|
||||
|
||||
void main()
|
||||
{
|
||||
|
|
|
@ -60,6 +60,7 @@ uniform vec2 textureSize;
|
|||
uniform float opacity;
|
||||
uniform float brightness;
|
||||
uniform float saturation;
|
||||
uniform uint shaderFlags;
|
||||
uniform sampler2D textureSampler;
|
||||
in vec2 texCoord;
|
||||
in vec2 onex;
|
||||
|
@ -67,8 +68,6 @@ in vec2 oney;
|
|||
in vec4 colorShift;
|
||||
out vec4 FragColor;
|
||||
|
||||
#define SourceSize vec4(textureSize, 1.0 / textureSize)
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform float SPOT_WIDTH;
|
||||
uniform float SPOT_HEIGHT;
|
||||
|
@ -95,8 +94,25 @@ uniform float OutputGamma;
|
|||
w = 1.0 - w * w; \
|
||||
w = w * w;
|
||||
|
||||
// shaderFlags:
|
||||
// 0x00000001 - Premultiplied alpha (BGRA)
|
||||
// 0x00000002 - Font texture
|
||||
// 0x00000004 - Post processing
|
||||
// 0x00000008 - Clipping
|
||||
// 0x00000010 - Screen rotated 90 or 270 degrees
|
||||
|
||||
void main()
|
||||
{
|
||||
bool rotated = false;
|
||||
if (0x0u != (shaderFlags & 0x10u))
|
||||
rotated = true;
|
||||
|
||||
vec4 SourceSize;
|
||||
if (rotated)
|
||||
SourceSize = vec4(textureSize.yx, 1.0 / textureSize.yx);
|
||||
else
|
||||
SourceSize = vec4(textureSize.xy, 1.0 / textureSize.xy);
|
||||
|
||||
vec2 coords = (texCoord * SourceSize.xy);
|
||||
vec2 pixel_center = floor(coords) + vec2(0.5, 0.5);
|
||||
vec2 texture_coords = pixel_center * SourceSize.zw;
|
||||
|
@ -127,7 +143,11 @@ void main()
|
|||
color = color + colorNB * vec4(h_weight_01);
|
||||
|
||||
// Vertical blending.
|
||||
float dy = coords.y - pixel_center.y;
|
||||
float dy;
|
||||
if (rotated)
|
||||
dy = coords.x - pixel_center.x;
|
||||
else
|
||||
dy = coords.y - pixel_center.y;
|
||||
float v_weight_00 = dy / SPOT_HEIGHT;
|
||||
WEIGHT(v_weight_00);
|
||||
color *= vec4(v_weight_00);
|
||||
|
|
Loading…
Reference in a new issue