Refactored the rendering code into proper classes.

This commit is contained in:
Leon Styhre 2022-03-14 19:51:48 +01:00
parent 4f21d94aa5
commit f0c35d8509
66 changed files with 1614 additions and 1457 deletions

View file

@ -1163,7 +1163,7 @@ void FileData::launchGame()
// flickering and to avoid showing the game launch message briefly when returning // flickering and to avoid showing the game launch message briefly when returning
// from the game. // from the game.
if (!runInBackground) if (!runInBackground)
Renderer::swapBuffers(); Renderer::getInstance()->swapBuffers();
Scripting::fireEvent("game-start", romPath, getSourceFileData()->metadata.get("name"), Scripting::fireEvent("game-start", romPath, getSourceFileData()->metadata.get("name"),
getSourceFileData()->getSystem()->getName(), getSourceFileData()->getSystem()->getName(),

View file

@ -13,7 +13,8 @@
#include "views/ViewController.h" #include "views/ViewController.h"
MediaViewer::MediaViewer() MediaViewer::MediaViewer()
: mVideo {nullptr} : mRenderer {Renderer::getInstance()}
, mVideo {nullptr}
, mImage {nullptr} , mImage {nullptr}
{ {
Window::getInstance()->setMediaViewer(this); Window::getInstance()->setMediaViewer(this);
@ -77,11 +78,11 @@ void MediaViewer::update(int deltaTime)
void MediaViewer::render(const glm::mat4& /*parentTrans*/) void MediaViewer::render(const glm::mat4& /*parentTrans*/)
{ {
glm::mat4 trans {Renderer::getIdentity()}; glm::mat4 trans {Renderer::getIdentity()};
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
// Render a black background below the game media. // Render a black background below the game media.
Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(), mRenderer->drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(),
0x000000FF, 0x000000FF); 0x000000FF, 0x000000FF);
if (mVideo && !mDisplayingImage) { if (mVideo && !mDisplayingImage) {
mVideo->render(trans); mVideo->render(trans);
@ -112,17 +113,17 @@ void MediaViewer::render(const glm::mat4& /*parentTrans*/)
} }
if (shaders != 0) if (shaders != 0)
Renderer::shaderPostprocessing(shaders, videoParameters); mRenderer->shaderPostprocessing(shaders, videoParameters);
} }
else if (mImage && mImage->hasImage() && mImage->getSize() != glm::vec2 {}) { else if (mImage && mImage->hasImage() && mImage->getSize() != glm::vec2 {}) {
mImage->render(trans); mImage->render(trans);
if (mCurrentImageIndex == mScreenshotIndex && if (mCurrentImageIndex == mScreenshotIndex &&
Settings::getInstance()->getBool("MediaViewerScreenshotScanlines")) Settings::getInstance()->getBool("MediaViewerScreenshotScanlines"))
Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES); mRenderer->shaderPostprocessing(Renderer::SHADER_SCANLINES);
else if (mCurrentImageIndex == mTitleScreenIndex && else if (mCurrentImageIndex == mTitleScreenIndex &&
Settings::getInstance()->getBool("MediaViewerScreenshotScanlines")) Settings::getInstance()->getBool("MediaViewerScreenshotScanlines"))
Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES); mRenderer->shaderPostprocessing(Renderer::SHADER_SCANLINES);
// This is necessary so that the video loops if viewing an image when // This is necessary so that the video loops if viewing an image when
// the video ends. // the video ends.

View file

@ -36,6 +36,7 @@ private:
void showNext() override; void showNext() override;
void showPrevious() override; void showPrevious() override;
Renderer* mRenderer;
FileData* mGame; FileData* mGame;
bool mHasVideo; bool mHasVideo;

View file

@ -30,7 +30,8 @@
#define FADE_TIME 300.0f #define FADE_TIME 300.0f
Screensaver::Screensaver() Screensaver::Screensaver()
: mWindow {Window::getInstance()} : mRenderer {Renderer::getInstance()}
, mWindow {Window::getInstance()}
, mState {STATE_INACTIVE} , mState {STATE_INACTIVE}
, mImageScreensaver {nullptr} , mImageScreensaver {nullptr}
, mVideoScreensaver {nullptr} , mVideoScreensaver {nullptr}
@ -238,12 +239,12 @@ void Screensaver::renderScreensaver()
{ {
std::string screensaverType = Settings::getInstance()->getString("ScreensaverType"); std::string screensaverType = Settings::getInstance()->getString("ScreensaverType");
glm::mat4 trans {Renderer::getIdentity()}; glm::mat4 trans {Renderer::getIdentity()};
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
if (mVideoScreensaver && screensaverType == "video") { if (mVideoScreensaver && screensaverType == "video") {
// Render a black background below the video. // Render a black background below the video.
Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(), mRenderer->drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(),
0x000000FF, 0x000000FF); 0x000000FF, 0x000000FF);
// Only render the video if the state requires it. // Only render the video if the state requires it.
if (static_cast<int>(mState) >= STATE_FADE_IN_VIDEO) if (static_cast<int>(mState) >= STATE_FADE_IN_VIDEO)
@ -251,8 +252,8 @@ void Screensaver::renderScreensaver()
} }
else if (mImageScreensaver && screensaverType == "slideshow") { else if (mImageScreensaver && screensaverType == "slideshow") {
// Render a black background below the image. // Render a black background below the image.
Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(), mRenderer->drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(),
0x000000FF, 0x000000FF); 0x000000FF, 0x000000FF);
// Only render the image if the state requires it. // Only render the image if the state requires it.
if (static_cast<int>(mState) >= STATE_FADE_IN_VIDEO) { if (static_cast<int>(mState) >= STATE_FADE_IN_VIDEO) {
@ -268,11 +269,11 @@ void Screensaver::renderScreensaver()
if (Settings::getInstance()->getString("ScreensaverType") == "slideshow") { if (Settings::getInstance()->getString("ScreensaverType") == "slideshow") {
if (mHasMediaFiles) { if (mHasMediaFiles) {
if (Settings::getInstance()->getBool("ScreensaverSlideshowScanlines")) if (Settings::getInstance()->getBool("ScreensaverSlideshowScanlines"))
Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES); mRenderer->shaderPostprocessing(Renderer::SHADER_SCANLINES);
if (Settings::getInstance()->getBool("ScreensaverSlideshowGameInfo") && if (Settings::getInstance()->getBool("ScreensaverSlideshowGameInfo") &&
mGameOverlay) { mGameOverlay) {
if (mGameOverlayRectangleCoords.size() == 4) { if (mGameOverlayRectangleCoords.size() == 4) {
Renderer::drawRect( mRenderer->drawRect(
mGameOverlayRectangleCoords[0], mGameOverlayRectangleCoords[1], mGameOverlayRectangleCoords[0], mGameOverlayRectangleCoords[1],
mGameOverlayRectangleCoords[2], mGameOverlayRectangleCoords[3], mGameOverlayRectangleCoords[2], mGameOverlayRectangleCoords[3],
0x00000000 | mRectangleFadeIn, 0x00000000 | mRectangleFadeIn); 0x00000000 | mRectangleFadeIn, 0x00000000 | mRectangleFadeIn);
@ -319,11 +320,11 @@ void Screensaver::renderScreensaver()
} }
if (shaders != 0) if (shaders != 0)
Renderer::shaderPostprocessing(shaders, videoParameters); mRenderer->shaderPostprocessing(shaders, videoParameters);
if (Settings::getInstance()->getBool("ScreensaverVideoGameInfo") && mGameOverlay) { if (Settings::getInstance()->getBool("ScreensaverVideoGameInfo") && mGameOverlay) {
if (mGameOverlayRectangleCoords.size() == 4) { if (mGameOverlayRectangleCoords.size() == 4) {
Renderer::drawRect( mRenderer->drawRect(
mGameOverlayRectangleCoords[0], mGameOverlayRectangleCoords[1], mGameOverlayRectangleCoords[0], mGameOverlayRectangleCoords[1],
mGameOverlayRectangleCoords[2], mGameOverlayRectangleCoords[3], mGameOverlayRectangleCoords[2], mGameOverlayRectangleCoords[3],
0x00000000 | mRectangleFadeIn, 0x00000000 | mRectangleFadeIn); 0x00000000 | mRectangleFadeIn, 0x00000000 | mRectangleFadeIn);
@ -347,7 +348,7 @@ void Screensaver::renderScreensaver()
Renderer::postProcessingParams dimParameters; Renderer::postProcessingParams dimParameters;
dimParameters.dimming = mDimValue; dimParameters.dimming = mDimValue;
dimParameters.saturation = mSaturationAmount; dimParameters.saturation = mSaturationAmount;
Renderer::shaderPostprocessing(Renderer::SHADER_CORE, dimParameters); mRenderer->shaderPostprocessing(Renderer::SHADER_CORE, dimParameters);
if (mDimValue > 0.63) if (mDimValue > 0.63)
mDimValue = glm::clamp(mDimValue - 0.015f, 0.68f, 1.0f); mDimValue = glm::clamp(mDimValue - 0.015f, 0.68f, 1.0f);
if (mSaturationAmount > 0.0) if (mSaturationAmount > 0.0)
@ -356,7 +357,7 @@ void Screensaver::renderScreensaver()
else if (Settings::getInstance()->getString("ScreensaverType") == "black") { else if (Settings::getInstance()->getString("ScreensaverType") == "black") {
Renderer::postProcessingParams blackParameters; Renderer::postProcessingParams blackParameters;
blackParameters.dimming = mDimValue; blackParameters.dimming = mDimValue;
Renderer::shaderPostprocessing(Renderer::SHADER_CORE, blackParameters); mRenderer->shaderPostprocessing(Renderer::SHADER_CORE, blackParameters);
if (mDimValue > 0.0) if (mDimValue > 0.0)
mDimValue = glm::clamp(mDimValue - 0.045f, 0.0f, 1.0f); mDimValue = glm::clamp(mDimValue - 0.045f, 0.0f, 1.0f);
} }
@ -567,8 +568,8 @@ void Screensaver::generateOverlayInfo()
if (mGameName == "" || mSystemName == "") if (mGameName == "" || mSystemName == "")
return; return;
float posX {Renderer::getWindowWidth() * 0.023f}; float posX {mRenderer->getWindowWidth() * 0.023f};
float posY {Renderer::getWindowHeight() * 0.02f}; float posY {mRenderer->getWindowHeight() * 0.02f};
std::string favoriteChar; std::string favoriteChar;
if (mCurrentGame && mCurrentGame->getFavorite()) if (mCurrentGame && mCurrentGame->getFavorite())
@ -595,7 +596,7 @@ void Screensaver::generateOverlayInfo()
else else
textSizeX = mGameOverlayFont[0].get()->sizeText(systemName).x; textSizeX = mGameOverlayFont[0].get()->sizeText(systemName).x;
float marginX {Renderer::getWindowWidth() * 0.01f}; float marginX {mRenderer->getWindowWidth() * 0.01f};
mGameOverlayRectangleCoords.clear(); mGameOverlayRectangleCoords.clear();
mGameOverlayRectangleCoords.push_back(posX - marginX); mGameOverlayRectangleCoords.push_back(posX - marginX);

View file

@ -58,6 +58,7 @@ private:
STATE_SCREENSAVER_ACTIVE STATE_SCREENSAVER_ACTIVE
}; };
Renderer* mRenderer;
Window* mWindow; Window* mWindow;
STATE mState; STATE mState;

View file

@ -24,6 +24,8 @@
#include "scrapers/Scraper.h" #include "scrapers/Scraper.h"
#include "views/ViewController.h" #include "views/ViewController.h"
#include <SDL2/SDL.h>
GuiGamelistOptions::GuiGamelistOptions(SystemData* system) GuiGamelistOptions::GuiGamelistOptions(SystemData* system)
: mMenu {"OPTIONS"} : mMenu {"OPTIONS"}
, mSystem {system} , mSystem {system}

View file

@ -15,7 +15,8 @@
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
GuiLaunchScreen::GuiLaunchScreen() GuiLaunchScreen::GuiLaunchScreen()
: mBackground {":/graphics/frame.svg"} : mRenderer {Renderer::getInstance()}
, mBackground {":/graphics/frame.svg"}
, mGrid {nullptr} , mGrid {nullptr}
, mMarquee {nullptr} , mMarquee {nullptr}
{ {
@ -224,7 +225,7 @@ void GuiLaunchScreen::render(const glm::mat4& /*parentTrans*/)
setScale(mScaleUp); setScale(mScaleUp);
glm::mat4 trans {Renderer::getIdentity() * getTransform()}; glm::mat4 trans {Renderer::getIdentity() * getTransform()};
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
GuiComponent::renderChildren(trans); GuiComponent::renderChildren(trans);

View file

@ -33,6 +33,7 @@ public:
void render(const glm::mat4& parentTrans) override; void render(const glm::mat4& parentTrans) override;
private: private:
Renderer* mRenderer;
NinePatchComponent mBackground; NinePatchComponent mBackground;
ComponentGrid* mGrid; ComponentGrid* mGrid;

View file

@ -38,7 +38,8 @@
#define FAILED_VERIFICATION_RETRIES 8 #define FAILED_VERIFICATION_RETRIES 8
GuiScraperSearch::GuiScraperSearch(SearchType type, unsigned int scrapeCount) GuiScraperSearch::GuiScraperSearch(SearchType type, unsigned int scrapeCount)
: mGrid {glm::ivec2 {5, 3}} : mRenderer {Renderer::getInstance()}
, mGrid {glm::ivec2 {5, 3}}
, mSearchType {type} , mSearchType {type}
, mScrapeCount {scrapeCount} , mScrapeCount {scrapeCount}
, mRefinedSearch {false} , mRefinedSearch {false}
@ -630,10 +631,10 @@ void GuiScraperSearch::render(const glm::mat4& parentTrans)
glm::mat4 trans {parentTrans * getTransform()}; glm::mat4 trans {parentTrans * getTransform()};
renderChildren(trans); renderChildren(trans);
Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0x00000009, 0x00000009); mRenderer->drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0x00000009, 0x00000009);
if (mBlockAccept) { if (mBlockAccept) {
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
mBusyAnim.render(trans); mBusyAnim.render(trans);
} }
} }

View file

@ -119,6 +119,7 @@ private:
// Resolve any metadata assets that need to be downloaded and return. // Resolve any metadata assets that need to be downloaded and return.
void returnResult(ScraperSearchResult result); void returnResult(ScraperSearchResult result);
Renderer* mRenderer;
ComponentGrid mGrid; ComponentGrid mGrid;
std::shared_ptr<TextComponent> mResultName; std::shared_ptr<TextComponent> mResultName;

View file

@ -21,6 +21,8 @@
#include "views/GamelistView.h" #include "views/GamelistView.h"
#include "views/ViewController.h" #include "views/ViewController.h"
#include <SDL2/SDL.h>
GuiSettings::GuiSettings(std::string title) GuiSettings::GuiSettings(std::string title)
: mMenu {title} : mMenu {title}
, mGoToSystem {nullptr} , mGoToSystem {nullptr}

View file

@ -57,6 +57,7 @@
namespace namespace
{ {
SDL_Event event {}; SDL_Event event {};
Renderer* renderer {nullptr};
Window* window {nullptr}; Window* window {nullptr};
int lastTime {0}; int lastTime {0};
@ -474,7 +475,7 @@ void applicationLoop()
window->update(deltaTime); window->update(deltaTime);
window->render(); window->render();
Renderer::swapBuffers(); renderer->swapBuffers();
Log::flush(); Log::flush();
#if !defined(__EMSCRIPTEN__) #if !defined(__EMSCRIPTEN__)
} }
@ -601,6 +602,7 @@ int main(int argc, char* argv[])
} }
} }
renderer = Renderer::getInstance();
window = Window::getInstance(); window = Window::getInstance();
ViewController::getInstance(); ViewController::getInstance();
CollectionSystemsManager::getInstance(); CollectionSystemsManager::getInstance();

View file

@ -18,8 +18,9 @@
GamelistView::GamelistView(FileData* root) GamelistView::GamelistView(FileData* root)
: GamelistBase {root} : GamelistBase {root}
, mLegacyMode {false} , mRenderer {Renderer::getInstance()}
, mViewStyle {ViewController::BASIC} , mViewStyle {ViewController::BASIC}
, mLegacyMode {false}
{ {
mViewStyle = ViewController::getInstance()->getState().viewstyle; mViewStyle = ViewController::getInstance()->getState().viewstyle;
@ -247,9 +248,9 @@ void GamelistView::render(const glm::mat4& parentTrans)
glm::ivec2 size {static_cast<int>(std::round(mSize.x * scaleX)), glm::ivec2 size {static_cast<int>(std::round(mSize.x * scaleX)),
static_cast<int>(std::round(mSize.y * scaleY))}; static_cast<int>(std::round(mSize.y * scaleY))};
Renderer::pushClipRect(pos, size); mRenderer->pushClipRect(pos, size);
renderChildren(trans); renderChildren(trans);
Renderer::popClipRect(); mRenderer->popClipRect();
} }
HelpStyle GamelistView::getHelpStyle() HelpStyle GamelistView::getHelpStyle()

View file

@ -102,8 +102,9 @@ private:
void legacyInitMDLabels(); void legacyInitMDLabels();
void legacyInitMDValues(); void legacyInitMDValues();
bool mLegacyMode; Renderer* mRenderer;
ViewController::GamelistViewStyle mViewStyle; ViewController::GamelistViewStyle mViewStyle;
bool mLegacyMode;
std::shared_ptr<ThemeData> mTheme; std::shared_ptr<ThemeData> mTheme;
std::vector<GuiComponent*> mThemeExtras; std::vector<GuiComponent*> mThemeExtras;

View file

@ -22,7 +22,8 @@
#endif #endif
SystemView::SystemView() SystemView::SystemView()
: mCamOffset {0.0f} : mRenderer {Renderer::getInstance()}
, mCamOffset {0.0f}
, mFadeOpacity {0.0f} , mFadeOpacity {0.0f}
, mPreviousScrollVelocity {0} , mPreviousScrollVelocity {0}
, mUpdatedGameCount {false} , mUpdatedGameCount {false}
@ -1048,7 +1049,7 @@ void SystemView::renderElements(const glm::mat4& parentTrans, bool abovePrimary)
elementTrans = glm::translate(elementTrans, elementTrans = glm::translate(elementTrans,
glm::vec3 {0.0f, (i - mCamOffset) * mSize.y, 0.0f}); glm::vec3 {0.0f, (i - mCamOffset) * mSize.y, 0.0f});
Renderer::pushClipRect( mRenderer->pushClipRect(
glm::ivec2 {static_cast<int>(glm::round(elementTrans[3].x)), glm::ivec2 {static_cast<int>(glm::round(elementTrans[3].x)),
static_cast<int>(glm::round(elementTrans[3].y))}, static_cast<int>(glm::round(elementTrans[3].y))},
glm::ivec2 {static_cast<int>(mSize.x), static_cast<int>(mSize.y)}); glm::ivec2 {static_cast<int>(mSize.x), static_cast<int>(mSize.y)});
@ -1081,7 +1082,7 @@ void SystemView::renderElements(const glm::mat4& parentTrans, bool abovePrimary)
mLegacySystemInfo->render(elementTrans); mLegacySystemInfo->render(elementTrans);
} }
Renderer::popClipRect(); mRenderer->popClipRect();
} }
} }
} }

View file

@ -108,6 +108,7 @@ private:
void legacyApplyTheme(const std::shared_ptr<ThemeData>& theme); void legacyApplyTheme(const std::shared_ptr<ThemeData>& theme);
void renderElements(const glm::mat4& parentTrans, bool abovePrimary); void renderElements(const glm::mat4& parentTrans, bool abovePrimary);
Renderer* mRenderer;
std::unique_ptr<CarouselComponent> mCarousel; std::unique_ptr<CarouselComponent> mCarousel;
std::unique_ptr<TextComponent> mLegacySystemInfo; std::unique_ptr<TextComponent> mLegacySystemInfo;
std::vector<SystemViewElements> mSystemElements; std::vector<SystemViewElements> mSystemElements;

View file

@ -31,7 +31,8 @@
#include "views/SystemView.h" #include "views/SystemView.h"
ViewController::ViewController() noexcept ViewController::ViewController() noexcept
: mNoGamesMessageBox {nullptr} : mRenderer {Renderer::getInstance()}
, mNoGamesMessageBox {nullptr}
, mCurrentView {nullptr} , mCurrentView {nullptr}
, mPreviousView {nullptr} , mPreviousView {nullptr}
, mSkipView {nullptr} , mSkipView {nullptr}
@ -201,7 +202,7 @@ void ViewController::invalidAlternativeEmulatorDialog()
void ViewController::goToStart(bool playTransition) void ViewController::goToStart(bool playTransition)
{ {
// Needed to avoid segfaults during emergency shutdown. // Needed to avoid segfaults during emergency shutdown.
if (Renderer::getSDLWindow() == nullptr) if (mRenderer->getSDLWindow() == nullptr)
return; return;
#if defined(__APPLE__) #if defined(__APPLE__)
@ -287,7 +288,7 @@ void ViewController::cancelViewTransitions()
void ViewController::stopScrolling() void ViewController::stopScrolling()
{ {
if (Renderer::getSDLWindow() == nullptr) if (mRenderer->getSDLWindow() == nullptr)
return; return;
mSystemListView->stopScrolling(); mSystemListView->stopScrolling();
@ -905,9 +906,9 @@ void ViewController::render(const glm::mat4& parentTrans)
// Fade out. // Fade out.
if (mFadeOpacity) { if (mFadeOpacity) {
unsigned int fadeColor = 0x00000000 | static_cast<unsigned char>(mFadeOpacity * 255); unsigned int fadeColor = 0x00000000 | static_cast<unsigned char>(mFadeOpacity * 255);
Renderer::setMatrix(parentTrans); mRenderer->setMatrix(parentTrans);
Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(), mRenderer->drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(),
fadeColor, fadeColor); fadeColor, fadeColor);
} }
} }
@ -999,7 +1000,7 @@ void ViewController::reloadGamelistView(GamelistView* view, bool reloadTheme)
void ViewController::reloadAll() void ViewController::reloadAll()
{ {
if (Renderer::getSDLWindow() == nullptr) if (mRenderer->getSDLWindow() == nullptr)
return; return;
cancelViewTransitions(); cancelViewTransitions();

View file

@ -151,6 +151,7 @@ private:
void launch(FileData* game); void launch(FileData* game);
Renderer* mRenderer;
std::string mNoGamesErrorMessage; std::string mNoGamesErrorMessage;
std::string mRomDirectory; std::string mRomDirectory;
GuiMsgBox* mNoGamesMessageBox; GuiMsgBox* mNoGamesMessageBox;

View file

@ -74,6 +74,7 @@ set(CORE_HEADERS
# Renderers # Renderers
${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Renderer.h ${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Renderer.h
${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Renderer_GL21.h
${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Shader_GL21.h ${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Shader_GL21.h
# Resources # Resources

View file

@ -23,7 +23,8 @@
#define CLOCK_BACKGROUND_CREATION false #define CLOCK_BACKGROUND_CREATION false
Window::Window() noexcept Window::Window() noexcept
: mScreensaver {nullptr} : mRenderer {Renderer::getInstance()}
, mScreensaver {nullptr}
, mMediaViewer {nullptr} , mMediaViewer {nullptr}
, mLaunchScreen {nullptr} , mLaunchScreen {nullptr}
, mInfoPopup {nullptr} , mInfoPopup {nullptr}
@ -102,7 +103,7 @@ GuiComponent* Window::peekGui()
bool Window::init() bool Window::init()
{ {
if (!Renderer::init()) { if (!mRenderer->init()) {
LOG(LogError) << "Renderer failed to initialize."; LOG(LogError) << "Renderer failed to initialize.";
return false; return false;
} }
@ -146,7 +147,7 @@ void Window::deinit()
InputManager::getInstance().deinit(); InputManager::getInstance().deinit();
ResourceManager::getInstance().unloadAll(); ResourceManager::getInstance().unloadAll();
Renderer::deinit(); mRenderer->deinit();
} }
void Window::input(InputConfig* config, Input input) void Window::input(InputConfig* config, Input input)
@ -476,16 +477,16 @@ void Window::render()
// Also dim the background slightly. // Also dim the background slightly.
backgroundParameters.dimming = 0.60f; backgroundParameters.dimming = 0.60f;
Renderer::shaderPostprocessing(Renderer::SHADER_CORE | mRenderer->shaderPostprocessing(Renderer::SHADER_CORE |
Renderer::SHADER_BLUR_HORIZONTAL | Renderer::SHADER_BLUR_HORIZONTAL |
Renderer::SHADER_BLUR_VERTICAL, Renderer::SHADER_BLUR_VERTICAL,
backgroundParameters, &processedTexture[0]); backgroundParameters, &processedTexture[0]);
} }
else { else {
// Dim the background slightly. // Dim the background slightly.
backgroundParameters.dimming = 0.60f; backgroundParameters.dimming = 0.60f;
Renderer::shaderPostprocessing(Renderer::SHADER_CORE, backgroundParameters, mRenderer->shaderPostprocessing(Renderer::SHADER_CORE, backgroundParameters,
&processedTexture[0]); &processedTexture[0]);
} }
mPostprocessedBackground->initFromPixels( mPostprocessedBackground->initFromPixels(
@ -546,10 +547,10 @@ void Window::render()
// Render the quick list scrolling overlay, which is triggered in IList. // Render the quick list scrolling overlay, which is triggered in IList.
if (mListScrollOpacity != 0.0f) { if (mListScrollOpacity != 0.0f) {
Renderer::setMatrix(Renderer::getIdentity()); mRenderer->setMatrix(Renderer::getIdentity());
Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(), mRenderer->drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(),
0x00000000 | static_cast<unsigned char>(mListScrollOpacity * 255.0f), 0x00000000 | static_cast<unsigned char>(mListScrollOpacity * 255.0f),
0x00000000 | static_cast<unsigned char>(mListScrollOpacity * 255.0f)); 0x00000000 | static_cast<unsigned char>(mListScrollOpacity * 255.0f));
glm::vec2 offset {mListScrollFont->sizeText(mListScrollText)}; glm::vec2 offset {mListScrollFont->sizeText(mListScrollText)};
offset.x = (Renderer::getScreenWidth() - offset.x) * 0.5f; offset.x = (Renderer::getScreenWidth() - offset.x) * 0.5f;
@ -604,7 +605,7 @@ void Window::render()
mLaunchScreen->render(trans); mLaunchScreen->render(trans);
if (Settings::getInstance()->getBool("DisplayGPUStatistics") && mFrameDataText) { if (Settings::getInstance()->getBool("DisplayGPUStatistics") && mFrameDataText) {
Renderer::setMatrix(Renderer::getIdentity()); mRenderer->setMatrix(Renderer::getIdentity());
mDefaultFonts.at(1)->renderTextCache(mFrameDataText.get()); mDefaultFonts.at(1)->renderTextCache(mFrameDataText.get());
} }
} }
@ -612,9 +613,9 @@ void Window::render()
void Window::renderLoadingScreen(std::string text) void Window::renderLoadingScreen(std::string text)
{ {
glm::mat4 trans {Renderer::getIdentity()}; glm::mat4 trans {Renderer::getIdentity()};
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(), mRenderer->drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(),
0x000000FF, 0x000000FF); 0x000000FF, 0x000000FF);
ImageComponent splash(true); ImageComponent splash(true);
splash.setImage(":/graphics/splash.svg"); splash.setImage(":/graphics/splash.svg");
@ -629,11 +630,11 @@ void Window::renderLoadingScreen(std::string text)
float x {std::round((Renderer::getScreenWidth() - cache->metrics.size.x) / 2.0f)}; float x {std::round((Renderer::getScreenWidth() - cache->metrics.size.x) / 2.0f)};
float y {std::round(Renderer::getScreenHeight() * 0.835f)}; float y {std::round(Renderer::getScreenHeight() * 0.835f)};
trans = glm::translate(trans, glm::vec3 {x, y, 0.0f}); trans = glm::translate(trans, glm::vec3 {x, y, 0.0f});
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
font->renderTextCache(cache); font->renderTextCache(cache);
delete cache; delete cache;
Renderer::swapBuffers(); mRenderer->swapBuffers();
} }
void Window::renderListScrollOverlay(const float opacity, const std::string& text) void Window::renderListScrollOverlay(const float opacity, const std::string& text)

View file

@ -159,6 +159,7 @@ private:
// Returns true if at least one component on the stack is processing. // Returns true if at least one component on the stack is processing.
bool isProcessing(); bool isProcessing();
Renderer* mRenderer;
HelpComponent* mHelp; HelpComponent* mHelp;
ImageComponent* mBackgroundOverlay; ImageComponent* mBackgroundOverlay;
float mBackgroundOverlayOpacity; float mBackgroundOverlayOpacity;

View file

@ -17,7 +17,8 @@ ButtonComponent::ButtonComponent(const std::string& text,
const std::function<void()>& func, const std::function<void()>& func,
bool upperCase, bool upperCase,
bool flatStyle) bool flatStyle)
: mBox {":/graphics/button.svg"} : mRenderer {Renderer::getInstance()}
, mBox {":/graphics/button.svg"}
, mFont {Font::get(FONT_SIZE_MEDIUM)} , mFont {Font::get(FONT_SIZE_MEDIUM)}
, mPadding {0.0f, 0.0f, 0.0f, 0.0f} , mPadding {0.0f, 0.0f, 0.0f, 0.0f}
, mFocused {false} , mFocused {false}
@ -112,16 +113,16 @@ void ButtonComponent::render(const glm::mat4& parentTrans)
if (mFlatStyle) { if (mFlatStyle) {
if (mFocused) { if (mFocused) {
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
Renderer::drawRect(mPadding.x, mPadding.y, mSize.x - mPadding.x - mPadding.z, mRenderer->drawRect(mPadding.x, mPadding.y, mSize.x - mPadding.x - mPadding.z,
mSize.y - mPadding.y - mPadding.w, mFlatColorFocused, mSize.y - mPadding.y - mPadding.w, mFlatColorFocused,
mFlatColorFocused); mFlatColorFocused);
} }
else { else {
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
Renderer::drawRect(mPadding.x, mPadding.y, mSize.x - mPadding.x - mPadding.z, mRenderer->drawRect(mPadding.x, mPadding.y, mSize.x - mPadding.x - mPadding.z,
mSize.y - mPadding.y - mPadding.w, mFlatColorUnfocused, mSize.y - mPadding.y - mPadding.w, mFlatColorUnfocused,
mFlatColorUnfocused); mFlatColorUnfocused);
} }
} }
else { else {
@ -134,13 +135,13 @@ void ButtonComponent::render(const glm::mat4& parentTrans)
trans = glm::translate(trans, centerOffset); trans = glm::translate(trans, centerOffset);
if (Settings::getInstance()->getBool("DebugText")) { if (Settings::getInstance()->getBool("DebugText")) {
Renderer::drawRect(centerOffset.x, 0.0f, mTextCache->metrics.size.x, mSize.y, mRenderer->drawRect(centerOffset.x, 0.0f, mTextCache->metrics.size.x, mSize.y,
0x00000033, 0x00000033); 0x00000033, 0x00000033);
Renderer::drawRect(mBox.getPosition().x, 0.0f, mBox.getSize().x, mSize.y, 0x0000FF33, mRenderer->drawRect(mBox.getPosition().x, 0.0f, mBox.getSize().x, mSize.y, 0x0000FF33,
0x0000FF33); 0x0000FF33);
} }
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
mTextCache->setColor(getCurTextColor()); mTextCache->setColor(getCurTextColor());
mFont->renderTextCache(mTextCache.get()); mFont->renderTextCache(mTextCache.get());

View file

@ -50,6 +50,7 @@ private:
unsigned int getCurTextColor() const; unsigned int getCurTextColor() const;
void updateImage(); void updateImage();
Renderer* mRenderer;
NinePatchComponent mBox; NinePatchComponent mBox;
std::shared_ptr<Font> mFont; std::shared_ptr<Font> mFont;

View file

@ -21,6 +21,7 @@ namespace
CarouselComponent::CarouselComponent() CarouselComponent::CarouselComponent()
: IList<CarouselElement, SystemData*> {LIST_SCROLL_STYLE_SLOW, LIST_ALWAYS_LOOP} : IList<CarouselElement, SystemData*> {LIST_SCROLL_STYLE_SLOW, LIST_ALWAYS_LOOP}
, mRenderer {Renderer::getInstance()}
, mCamOffset {0.0f} , mCamOffset {0.0f}
, mPreviousScrollVelocity {0} , mPreviousScrollVelocity {0}
, mType {HORIZONTAL} , mType {HORIZONTAL}
@ -194,11 +195,11 @@ void CarouselComponent::render(const glm::mat4& parentTrans)
carouselTrans, glm::vec3 {mOrigin.x * mSize.x * -1.0f, mOrigin.y * mSize.y * -1.0f, 0.0f}); carouselTrans, glm::vec3 {mOrigin.x * mSize.x * -1.0f, mOrigin.y * mSize.y * -1.0f, 0.0f});
glm::vec2 clipPos {carouselTrans[3].x, carouselTrans[3].y}; glm::vec2 clipPos {carouselTrans[3].x, carouselTrans[3].y};
Renderer::setMatrix(carouselTrans); mRenderer->setMatrix(carouselTrans);
// Background box behind logos. // Background box behind logos.
Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, mCarouselColor, mCarouselColorEnd, mRenderer->drawRect(0.0f, 0.0f, mSize.x, mSize.y, mCarouselColor, mCarouselColorEnd,
mColorGradientHorizontal); mColorGradientHorizontal);
// Draw logos. // Draw logos.
// logoSpacing will also include the size of the logo itself. // logoSpacing will also include the size of the logo itself.

View file

@ -68,6 +68,7 @@ protected:
} }
private: private:
Renderer* mRenderer;
std::function<void(CursorState state)> mCursorChangedCallback; std::function<void(CursorState state)> mCursorChangedCallback;
std::function<void()> mCancelTransitionsCallback; std::function<void()> mCancelTransitionsCallback;

View file

@ -13,7 +13,8 @@
using namespace GridFlags; using namespace GridFlags;
ComponentGrid::ComponentGrid(const glm::ivec2& gridDimensions) ComponentGrid::ComponentGrid(const glm::ivec2& gridDimensions)
: mGridSize {gridDimensions} : mRenderer {Renderer::getInstance()}
, mGridSize {gridDimensions}
, mCursor {0, 0} , mCursor {0, 0}
{ {
assert(gridDimensions.x > 0 && gridDimensions.y > 0); assert(gridDimensions.x > 0 && gridDimensions.y > 0);
@ -429,9 +430,9 @@ void ComponentGrid::render(const glm::mat4& parentTrans)
// Draw cell separators. // Draw cell separators.
for (size_t i = 0; i < mSeparators.size(); ++i) { for (size_t i = 0; i < mSeparators.size(); ++i) {
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
Renderer::drawRect(mSeparators[i][0], mSeparators[i][1], mSeparators[i][2], mRenderer->drawRect(mSeparators[i][0], mSeparators[i][1], mSeparators[i][2],
mSeparators[i][3], 0xC6C7C6FF, 0xC6C7C6FF); mSeparators[i][3], 0xC6C7C6FF, 0xC6C7C6FF);
} }
} }

View file

@ -128,6 +128,7 @@ private:
const GridEntry* getCellAt(int x, int y) const; const GridEntry* getCellAt(int x, int y) const;
const GridEntry* getCellAt(const glm::ivec2& pos) const { return getCellAt(pos.x, pos.y); } const GridEntry* getCellAt(const glm::ivec2& pos) const { return getCellAt(pos.x, pos.y); }
Renderer* mRenderer;
std::vector<std::vector<float>> mSeparators; std::vector<std::vector<float>> mSeparators;
glm::ivec2 mGridSize; glm::ivec2 mGridSize;
std::vector<GridEntry> mCells; std::vector<GridEntry> mCells;

View file

@ -14,6 +14,7 @@
ComponentList::ComponentList() ComponentList::ComponentList()
: IList<ComponentListRow, void*> {LIST_SCROLL_STYLE_SLOW, LIST_NEVER_LOOP} : IList<ComponentListRow, void*> {LIST_SCROLL_STYLE_SLOW, LIST_NEVER_LOOP}
, mRenderer {Renderer::getInstance()}
, mFocused {false} , mFocused {false}
, mSetupCompleted {false} , mSetupCompleted {false}
, mBottomCameraOffset {false} , mBottomCameraOffset {false}
@ -294,8 +295,8 @@ void ComponentList::render(const glm::mat4& parentTrans)
const int clipRectSizeX {static_cast<int>(std::round(dim.x))}; const int clipRectSizeX {static_cast<int>(std::round(dim.x))};
const int clipRectSizeY {static_cast<int>(std::round(dim.y))}; const int clipRectSizeY {static_cast<int>(std::round(dim.y))};
Renderer::pushClipRect(glm::ivec2 {clipRectPosX, clipRectPosY}, mRenderer->pushClipRect(glm::ivec2 {clipRectPosX, clipRectPosY},
glm::ivec2 {clipRectSizeX, clipRectSizeY}); glm::ivec2 {clipRectSizeX, clipRectSizeY});
// Scroll the camera. // Scroll the camera.
trans = glm::translate(trans, glm::vec3 {0.0f, -mCameraOffset, 0.0f}); trans = glm::translate(trans, glm::vec3 {0.0f, -mCameraOffset, 0.0f});
@ -374,20 +375,21 @@ void ComponentList::render(const glm::mat4& parentTrans)
} }
// Custom rendering. // Custom rendering.
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
// Draw selector bar. // Draw selector bar.
if (mFocused) { if (mFocused) {
const float selectedRowHeight = getRowHeight(mEntries.at(mCursor).data); const float selectedRowHeight = getRowHeight(mEntries.at(mCursor).data);
if (mOpacity == 1.0f) { if (mOpacity == 1.0f) {
Renderer::drawRect(0.0f, mSelectorBarOffset, std::ceil(mSize.x), selectedRowHeight, mRenderer->drawRect(0.0f, mSelectorBarOffset, std::ceil(mSize.x), selectedRowHeight,
0xFFFFFFFF, 0xFFFFFFFF, false, mOpacity, mDimming, 0xFFFFFFFF, 0xFFFFFFFF, false, mOpacity, mDimming,
Renderer::Blend::ONE_MINUS_DST_COLOR, Renderer::Blend::ZERO); Renderer::BlendFactor::ONE_MINUS_DST_COLOR,
Renderer::BlendFactor::ZERO);
Renderer::drawRect(0.0f, mSelectorBarOffset, std::ceil(mSize.x), selectedRowHeight, mRenderer->drawRect(0.0f, mSelectorBarOffset, std::ceil(mSize.x), selectedRowHeight,
0x777777FF, 0x777777FF, false, mOpacity, mDimming, 0x777777FF, 0x777777FF, false, mOpacity, mDimming,
Renderer::Blend::ONE, Renderer::Blend::ONE); Renderer::BlendFactor::ONE, Renderer::BlendFactor::ONE);
} }
for (auto it = drawAfterCursor.cbegin(); it != drawAfterCursor.cend(); ++it) for (auto it = drawAfterCursor.cbegin(); it != drawAfterCursor.cend(); ++it)
@ -395,20 +397,20 @@ void ComponentList::render(const glm::mat4& parentTrans)
// Reset matrix if one of these components changed it. // Reset matrix if one of these components changed it.
if (drawAfterCursor.size()) if (drawAfterCursor.size())
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
} }
// Draw separators. // Draw separators.
float y = 0; float y = 0;
for (unsigned int i = 0; i < mEntries.size(); ++i) { for (unsigned int i = 0; i < mEntries.size(); ++i) {
Renderer::drawRect(0.0f, y, std::ceil(mSize.x), 1.0f * Renderer::getScreenHeightModifier(), mRenderer->drawRect(0.0f, y, std::ceil(mSize.x), 1.0f * Renderer::getScreenHeightModifier(),
0xC6C7C6FF, 0xC6C7C6FF, false, mOpacity, mDimming); 0xC6C7C6FF, 0xC6C7C6FF, false, mOpacity, mDimming);
y += getRowHeight(mEntries.at(i).data); y += getRowHeight(mEntries.at(i).data);
} }
Renderer::drawRect(0.0f, y, std::ceil(mSize.x), 1.0f * Renderer::getScreenHeightModifier(), mRenderer->drawRect(0.0f, y, std::ceil(mSize.x), 1.0f * Renderer::getScreenHeightModifier(),
0xC6C7C6FF, 0xC6C7C6FF, false, mOpacity, mDimming); 0xC6C7C6FF, 0xC6C7C6FF, false, mOpacity, mDimming);
Renderer::popClipRect(); mRenderer->popClipRect();
} }
float ComponentList::getRowHeight(const ComponentListRow& row) const float ComponentList::getRowHeight(const ComponentListRow& row) const

View file

@ -124,6 +124,7 @@ protected:
void onCursorChanged(const CursorState& state) override; void onCursorChanged(const CursorState& state) override;
private: private:
Renderer* mRenderer;
bool mFocused; bool mFocused;
bool mSetupCompleted; bool mSetupCompleted;
bool mBottomCameraOffset; bool mBottomCameraOffset;

View file

@ -16,7 +16,8 @@
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
DateTimeEditComponent::DateTimeEditComponent(bool alignRight, DisplayMode dispMode) DateTimeEditComponent::DateTimeEditComponent(bool alignRight, DisplayMode dispMode)
: mEditing {false} : mRenderer {Renderer::getInstance()}
, mEditing {false}
, mEditIndex {0} , mEditIndex {0}
, mDisplayMode {dispMode} , mDisplayMode {dispMode}
, mKeyRepeatDir {0} , mKeyRepeatDir {0}
@ -181,16 +182,16 @@ void DateTimeEditComponent::render(const glm::mat4& parentTrans)
off.x += referenceSize - mTextCache->metrics.size.x; off.x += referenceSize - mTextCache->metrics.size.x;
trans = glm::translate(trans, off); trans = glm::translate(trans, off);
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
if (Settings::getInstance()->getBool("DebugText")) { if (Settings::getInstance()->getBool("DebugText")) {
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
if (mTextCache->metrics.size.x > 0.0f) { if (mTextCache->metrics.size.x > 0.0f) {
Renderer::drawRect(0.0f, 0.0f - off.y, mSize.x - off.x, mSize.y, 0x0000FF33, mRenderer->drawRect(0.0f, 0.0f - off.y, mSize.x - off.x, mSize.y, 0x0000FF33,
0x0000FF33); 0x0000FF33);
} }
Renderer::drawRect(0.0f, 0.0f, mTextCache->metrics.size.x, mTextCache->metrics.size.y, mRenderer->drawRect(0.0f, 0.0f, mTextCache->metrics.size.x, mTextCache->metrics.size.y,
0x00000033, 0x00000033); 0x00000033, 0x00000033);
} }
mTextCache->setColor((mColor & 0xFFFFFF00) | static_cast<int>(getOpacity() * 255.0f)); mTextCache->setColor((mColor & 0xFFFFFF00) | static_cast<int>(getOpacity() * 255.0f));
@ -198,9 +199,9 @@ void DateTimeEditComponent::render(const glm::mat4& parentTrans)
if (mEditing && mTime != 0) { if (mEditing && mTime != 0) {
if (mEditIndex >= 0 && static_cast<unsigned int>(mEditIndex) < mCursorBoxes.size()) if (mEditIndex >= 0 && static_cast<unsigned int>(mEditIndex) < mCursorBoxes.size())
Renderer::drawRect(mCursorBoxes[mEditIndex][0], mCursorBoxes[mEditIndex][1], mRenderer->drawRect(mCursorBoxes[mEditIndex][0], mCursorBoxes[mEditIndex][1],
mCursorBoxes[mEditIndex][2], mCursorBoxes[mEditIndex][3], mCursorBoxes[mEditIndex][2], mCursorBoxes[mEditIndex][3],
0x00000022, 0x00000022); 0x00000022, 0x00000022);
} }
} }
} }

View file

@ -10,6 +10,7 @@
#define ES_CORE_COMPONENTS_DATE_TIME_EDIT_COMPONENT_H #define ES_CORE_COMPONENTS_DATE_TIME_EDIT_COMPONENT_H
#include "GuiComponent.h" #include "GuiComponent.h"
#include "renderers/Renderer.h"
#include "utils/TimeUtil.h" #include "utils/TimeUtil.h"
class TextCache; class TextCache;
@ -66,6 +67,7 @@ private:
void changeDate(); void changeDate();
void updateTextCache(); void updateTextCache();
Renderer* mRenderer;
Utils::Time::DateTime mTime; Utils::Time::DateTime mTime;
Utils::Time::DateTime mTimeBeforeEdit; Utils::Time::DateTime mTimeBeforeEdit;

View file

@ -20,7 +20,8 @@
#include "ThemeData.h" #include "ThemeData.h"
FlexboxComponent::FlexboxComponent(std::vector<FlexboxItem>& items) FlexboxComponent::FlexboxComponent(std::vector<FlexboxItem>& items)
: mItems {items} : mRenderer {Renderer::getInstance()}
, mItems {items}
, mDirection {DEFAULT_DIRECTION} , mDirection {DEFAULT_DIRECTION}
, mAlignment {DEFAULT_ALIGNMENT} , mAlignment {DEFAULT_ALIGNMENT}
, mLines {DEFAULT_LINES} , mLines {DEFAULT_LINES}
@ -42,10 +43,10 @@ void FlexboxComponent::render(const glm::mat4& parentTrans)
computeLayout(); computeLayout();
glm::mat4 trans {parentTrans * getTransform()}; glm::mat4 trans {parentTrans * getTransform()};
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
if (Settings::getInstance()->getBool("DebugImage")) if (Settings::getInstance()->getBool("DebugImage"))
Renderer::drawRect(0.0f, 0.0f, ceilf(mSize.x), ceilf(mSize.y), 0xFF000033, 0xFF000033); mRenderer->drawRect(0.0f, 0.0f, ceilf(mSize.x), ceilf(mSize.y), 0xFF000033, 0xFF000033);
for (auto& item : mItems) { for (auto& item : mItems) {
if (!item.visible) if (!item.visible)

View file

@ -81,6 +81,7 @@ private:
// Calculate flexbox layout. // Calculate flexbox layout.
void computeLayout(); void computeLayout();
Renderer* mRenderer;
std::vector<FlexboxItem>& mItems; std::vector<FlexboxItem>& mItems;
// Layout options. // Layout options.

View file

@ -20,7 +20,8 @@
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
GIFAnimComponent::GIFAnimComponent() GIFAnimComponent::GIFAnimComponent()
: mFrameSize {0} : mRenderer {Renderer::getInstance()}
, mFrameSize {0}
, mAnimFile {nullptr} , mAnimFile {nullptr}
, mAnimation {nullptr} , mAnimation {nullptr}
, mFrame {nullptr} , mFrame {nullptr}
@ -466,10 +467,10 @@ void GIFAnimComponent::render(const glm::mat4& parentTrans)
} }
} }
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
if (Settings::getInstance()->getBool("DebugImage")) if (Settings::getInstance()->getBool("DebugImage"))
Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0xFF000033, 0xFF000033); mRenderer->drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0xFF000033, 0xFF000033);
if (mTexture->getSize().x != 0.0f) { if (mTexture->getSize().x != 0.0f) {
mTexture->bind(); mTexture->bind();
@ -493,6 +494,6 @@ void GIFAnimComponent::render(const glm::mat4& parentTrans)
vertices->convertBGRAToRGBA = true; vertices->convertBGRAToRGBA = true;
// Render it. // Render it.
Renderer::drawTriangleStrips(&vertices[0], 4); mRenderer->drawTriangleStrips(&vertices[0], 4);
} }
} }

View file

@ -69,6 +69,7 @@ private:
return ftell(reinterpret_cast<FILE*>(handle)); return ftell(reinterpret_cast<FILE*>(handle));
} }
Renderer* mRenderer;
std::shared_ptr<TextureResource> mTexture; std::shared_ptr<TextureResource> mTexture;
std::vector<uint8_t> mPictureRGBA; std::vector<uint8_t> mPictureRGBA;
size_t mFrameSize; size_t mFrameSize;

View file

@ -30,7 +30,8 @@ glm::vec2 ImageComponent::getSize() const
} }
ImageComponent::ImageComponent(bool forceLoad, bool dynamic) ImageComponent::ImageComponent(bool forceLoad, bool dynamic)
: mTargetSize {0, 0} : mRenderer {Renderer::getInstance()}
, mTargetSize {0, 0}
, mFlipX {false} , mFlipX {false}
, mFlipY {false} , mFlipY {false}
, mTargetIsMax {false} , mTargetIsMax {false}
@ -396,14 +397,14 @@ void ImageComponent::render(const glm::mat4& parentTrans)
return; return;
glm::mat4 trans {parentTrans * getTransform()}; glm::mat4 trans {parentTrans * getTransform()};
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
if (mTexture && mOpacity > 0.0f) { if (mTexture && mOpacity > 0.0f) {
if (Settings::getInstance()->getBool("DebugImage")) { if (Settings::getInstance()->getBool("DebugImage")) {
glm::vec2 targetSizePos {(mTargetSize - mSize) * mOrigin * glm::vec2 {-1.0f}}; glm::vec2 targetSizePos {(mTargetSize - mSize) * mOrigin * glm::vec2 {-1.0f}};
Renderer::drawRect(targetSizePos.x, targetSizePos.y, mTargetSize.x, mTargetSize.y, mRenderer->drawRect(targetSizePos.x, targetSizePos.y, mTargetSize.x, mTargetSize.y,
0xFF000033, 0xFF000033); 0xFF000033, 0xFF000033);
Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0xFF000033, 0xFF000033); mRenderer->drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0xFF000033, 0xFF000033);
} }
// An image with zero size would normally indicate a corrupt image file. // An image with zero size would normally indicate a corrupt image file.
if (mTexture->getSize() != glm::ivec2 {}) { if (mTexture->getSize() != glm::ivec2 {}) {
@ -422,7 +423,7 @@ void ImageComponent::render(const glm::mat4& parentTrans)
mVertices->opacity = mThemeOpacity; mVertices->opacity = mThemeOpacity;
mVertices->dimming = mDimming; mVertices->dimming = mDimming;
Renderer::drawTriangleStrips(&mVertices[0], 4); mRenderer->drawTriangleStrips(&mVertices[0], 4);
} }
else { else {
if (!mTexture) { if (!mTexture) {

View file

@ -102,6 +102,7 @@ public:
std::vector<HelpPrompt> getHelpPrompts() override; std::vector<HelpPrompt> getHelpPrompts() override;
private: private:
Renderer* mRenderer;
glm::vec2 mTargetSize; glm::vec2 mTargetSize;
bool mFlipX; bool mFlipX;

View file

@ -16,7 +16,8 @@
#include "resources/ResourceManager.h" #include "resources/ResourceManager.h"
LottieAnimComponent::LottieAnimComponent() LottieAnimComponent::LottieAnimComponent()
: mCacheFrames {true} : mRenderer {Renderer::getInstance()}
, mCacheFrames {true}
, mMaxCacheSize {0} , mMaxCacheSize {0}
, mCacheSize {0} , mCacheSize {0}
, mFrameSize {0} , mFrameSize {0}
@ -53,8 +54,8 @@ LottieAnimComponent::LottieAnimComponent()
// Set component defaults. // Set component defaults.
setOrigin(0.5f, 0.5f); setOrigin(0.5f, 0.5f);
setSize(Renderer::getScreenWidth() * 0.2f, Renderer::getScreenHeight() * 0.2f); setSize(mRenderer->getScreenWidth() * 0.2f, mRenderer->getScreenHeight() * 0.2f);
setPosition(Renderer::getScreenWidth() * 0.3f, Renderer::getScreenHeight() * 0.3f); setPosition(mRenderer->getScreenWidth() * 0.3f, mRenderer->getScreenHeight() * 0.3f);
setDefaultZIndex(10.0f); setDefaultZIndex(10.0f);
setZIndex(10.0f); setZIndex(10.0f);
} }
@ -455,10 +456,10 @@ void LottieAnimComponent::render(const glm::mat4& parentTrans)
} }
} }
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
if (Settings::getInstance()->getBool("DebugImage")) if (Settings::getInstance()->getBool("DebugImage"))
Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0xFF000033, 0xFF000033); mRenderer->drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0xFF000033, 0xFF000033);
if (mTexture->getSize().x != 0.0f) { if (mTexture->getSize().x != 0.0f) {
mTexture->bind(); mTexture->bind();
@ -482,6 +483,6 @@ void LottieAnimComponent::render(const glm::mat4& parentTrans)
vertices->convertBGRAToRGBA = true; vertices->convertBGRAToRGBA = true;
// Render it. // Render it.
Renderer::drawTriangleStrips(&vertices[0], 4); mRenderer->drawTriangleStrips(&vertices[0], 4);
} }
} }

View file

@ -48,6 +48,7 @@ public:
private: private:
void render(const glm::mat4& parentTrans) override; void render(const glm::mat4& parentTrans) override;
Renderer* mRenderer;
std::shared_ptr<TextureResource> mTexture; std::shared_ptr<TextureResource> mTexture;
std::vector<uint8_t> mPictureRGBA; std::vector<uint8_t> mPictureRGBA;
std::unordered_map<size_t, std::vector<uint8_t>> mFrameCache; std::unordered_map<size_t, std::vector<uint8_t>> mFrameCache;

View file

@ -16,7 +16,8 @@
NinePatchComponent::NinePatchComponent(const std::string& path, NinePatchComponent::NinePatchComponent(const std::string& path,
unsigned int edgeColor, unsigned int edgeColor,
unsigned int centerColor) unsigned int centerColor)
: mVertices {nullptr} : mRenderer {Renderer::getInstance()}
, mVertices {nullptr}
, mPath {path} , mPath {path}
, mCornerSize {16.0f, 16.0f} , mCornerSize {16.0f, 16.0f}
, mSharpCorners {false} , mSharpCorners {false}
@ -131,10 +132,10 @@ void NinePatchComponent::render(const glm::mat4& parentTrans)
glm::mat4 trans {parentTrans * getTransform()}; glm::mat4 trans {parentTrans * getTransform()};
if (mTexture && mVertices != nullptr) { if (mTexture && mVertices != nullptr) {
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
mVertices->opacity = mOpacity; mVertices->opacity = mOpacity;
mTexture->bind(); mTexture->bind();
Renderer::drawTriangleStrips(&mVertices[0], 6 * 9); mRenderer->drawTriangleStrips(&mVertices[0], 6 * 9);
} }
renderChildren(trans); renderChildren(trans);

View file

@ -62,6 +62,7 @@ private:
void buildVertices(); void buildVertices();
void updateColors(); void updateColors();
Renderer* mRenderer;
Renderer::Vertex* mVertices; Renderer::Vertex* mVertices;
std::string mPath; std::string mPath;

View file

@ -14,7 +14,8 @@
#include "resources/TextureResource.h" #include "resources/TextureResource.h"
RatingComponent::RatingComponent(bool colorizeChanges) RatingComponent::RatingComponent(bool colorizeChanges)
: mColorOriginalValue {DEFAULT_COLORSHIFT} : mRenderer {Renderer::getInstance()}
, mColorOriginalValue {DEFAULT_COLORSHIFT}
, mColorChangedValue {DEFAULT_COLORSHIFT} , mColorChangedValue {DEFAULT_COLORSHIFT}
, mColorShift {DEFAULT_COLORSHIFT} , mColorShift {DEFAULT_COLORSHIFT}
, mColorShiftEnd {DEFAULT_COLORSHIFT} , mColorShiftEnd {DEFAULT_COLORSHIFT}
@ -152,12 +153,12 @@ void RatingComponent::render(const glm::mat4& parentTrans)
glm::mat4 trans {parentTrans * getTransform()}; glm::mat4 trans {parentTrans * getTransform()};
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
if (mOpacity > 0.0f) { if (mOpacity > 0.0f) {
if (Settings::getInstance()->getBool("DebugImage")) { if (Settings::getInstance()->getBool("DebugImage")) {
Renderer::drawRect(0.0f, 0.0f, mSize.y * NUM_RATING_STARS, mSize.y, 0xFF000033, mRenderer->drawRect(0.0f, 0.0f, mSize.y * NUM_RATING_STARS, mSize.y, 0xFF000033,
0xFF000033); 0xFF000033);
} }
if (mUnfilledTexture->bind()) { if (mUnfilledTexture->bind()) {
@ -167,16 +168,16 @@ void RatingComponent::render(const glm::mat4& parentTrans)
(mUnfilledColor & 0xFFFFFF00) + (mVertices[i].color & 0x000000FF); (mUnfilledColor & 0xFFFFFF00) + (mVertices[i].color & 0x000000FF);
} }
Renderer::drawTriangleStrips(&mVertices[4], 4); mRenderer->drawTriangleStrips(&mVertices[4], 4);
Renderer::bindTexture(0); mRenderer->bindTexture(0);
if (mUnfilledColor != mColorShift) if (mUnfilledColor != mColorShift)
updateColors(); updateColors();
} }
if (mFilledTexture->bind()) { if (mFilledTexture->bind()) {
Renderer::drawTriangleStrips(&mVertices[0], 4); mRenderer->drawTriangleStrips(&mVertices[0], 4);
Renderer::bindTexture(0); mRenderer->bindTexture(0);
} }
} }

View file

@ -52,6 +52,7 @@ private:
void updateVertices(); void updateVertices();
void updateColors(); void updateColors();
Renderer* mRenderer;
float mValue; float mValue;
int mOriginalValue; int mOriginalValue;
unsigned int mColorOriginalValue; unsigned int mColorOriginalValue;

View file

@ -15,7 +15,8 @@
#include "resources/Font.h" #include "resources/Font.h"
ScrollableContainer::ScrollableContainer() ScrollableContainer::ScrollableContainer()
: mScrollPos {0.0f, 0.0f} : mRenderer {Renderer::getInstance()}
, mScrollPos {0.0f, 0.0f}
, mScrollDir {0.0f, 0.0f} , mScrollDir {0.0f, 0.0f}
, mClipSpacing {0.0f} , mClipSpacing {0.0f}
, mAutoScrollDelay {0} , mAutoScrollDelay {0}
@ -233,11 +234,11 @@ void ScrollableContainer::render(const glm::mat4& parentTrans)
clipPos.y += static_cast<int>(mClipSpacing); clipPos.y += static_cast<int>(mClipSpacing);
clipDim.y -= static_cast<int>(mClipSpacing); clipDim.y -= static_cast<int>(mClipSpacing);
Renderer::pushClipRect(clipPos, clipDim); mRenderer->pushClipRect(clipPos, clipDim);
trans = glm::translate(trans, -glm::vec3 {mScrollPos.x, mScrollPos.y, 0.0f}); trans = glm::translate(trans, -glm::vec3 {mScrollPos.x, mScrollPos.y, 0.0f});
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
GuiComponent::renderChildren(trans); GuiComponent::renderChildren(trans);
Renderer::popClipRect(); mRenderer->popClipRect();
} }

View file

@ -18,6 +18,7 @@
#define AUTO_SCROLL_SPEED 4.0f #define AUTO_SCROLL_SPEED 4.0f
#include "GuiComponent.h" #include "GuiComponent.h"
#include "renderers/Renderer.h"
class ScrollableContainer : public GuiComponent class ScrollableContainer : public GuiComponent
{ {
@ -42,6 +43,7 @@ public:
void render(const glm::mat4& parentTrans) override; void render(const glm::mat4& parentTrans) override;
private: private:
Renderer* mRenderer;
glm::vec2 mScrollPos; glm::vec2 mScrollPos;
glm::vec2 mScrollDir; glm::vec2 mScrollDir;

View file

@ -15,7 +15,8 @@
#define MOVE_REPEAT_RATE 40 #define MOVE_REPEAT_RATE 40
SliderComponent::SliderComponent(float min, float max, float increment, const std::string& suffix) SliderComponent::SliderComponent(float min, float max, float increment, const std::string& suffix)
: mMin {min} : mRenderer {Renderer::getInstance()}
, mMin {min}
, mMax {max} , mMax {max}
, mSingleIncrement {increment} , mSingleIncrement {increment}
, mMoveRate {0.0f} , mMoveRate {0.0f}
@ -77,14 +78,14 @@ void SliderComponent::update(int deltaTime)
void SliderComponent::render(const glm::mat4& parentTrans) void SliderComponent::render(const glm::mat4& parentTrans)
{ {
glm::mat4 trans {parentTrans * getTransform()}; glm::mat4 trans {parentTrans * getTransform()};
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
if (Settings::getInstance()->getBool("DebugText")) { if (Settings::getInstance()->getBool("DebugText")) {
Renderer::drawRect( mRenderer->drawRect(
mSize.x - mTextCache->metrics.size.x, (mSize.y - mTextCache->metrics.size.y) / 2.0f, mSize.x - mTextCache->metrics.size.x, (mSize.y - mTextCache->metrics.size.y) / 2.0f,
mTextCache->metrics.size.x, mTextCache->metrics.size.y, 0x0000FF33, 0x0000FF33); mTextCache->metrics.size.x, mTextCache->metrics.size.y, 0x0000FF33, 0x0000FF33);
Renderer::drawRect(mSize.x - mTextCache->metrics.size.x, 0.0f, mTextCache->metrics.size.x, mRenderer->drawRect(mSize.x - mTextCache->metrics.size.x, 0.0f, mTextCache->metrics.size.x,
mSize.y, 0x00000033, 0x00000033); mSize.y, 0x00000033, 0x00000033);
} }
float width {mSize.x - mKnob.getSize().x - float width {mSize.x - mKnob.getSize().x -
@ -97,8 +98,8 @@ void SliderComponent::render(const glm::mat4& parentTrans)
mFont->renderTextCache(mTextCache.get()); mFont->renderTextCache(mTextCache.get());
// Render bar. // Render bar.
Renderer::drawRect(mKnob.getSize().x / 2.0f, mSize.y / 2.0f - mBarHeight / 2.0f, width, mRenderer->drawRect(mKnob.getSize().x / 2.0f, mSize.y / 2.0f - mBarHeight / 2.0f, width,
mBarHeight, 0x777777FF, 0x777777FF); mBarHeight, 0x777777FF, 0x777777FF);
// Render knob. // Render knob.
mKnob.render(trans); mKnob.render(trans);

View file

@ -40,6 +40,7 @@ public:
private: private:
void onValueChanged(); void onValueChanged();
Renderer* mRenderer;
float mMin, mMax; float mMin, mMax;
float mValue; float mValue;
float mSingleIncrement; float mSingleIncrement;

View file

@ -14,6 +14,7 @@
TextComponent::TextComponent() TextComponent::TextComponent()
: mFont {Font::get(FONT_SIZE_MEDIUM)} : mFont {Font::get(FONT_SIZE_MEDIUM)}
, mRenderer {Renderer::getInstance()}
, mColor {0x000000FF} , mColor {0x000000FF}
, mBgColor {0x00000000} , mBgColor {0x00000000}
, mColorOpacity {1.0f} , mColorOpacity {1.0f}
@ -39,6 +40,7 @@ TextComponent::TextComponent(const std::string& text,
glm::vec2 size, glm::vec2 size,
unsigned int bgcolor) unsigned int bgcolor)
: mFont {nullptr} : mFont {nullptr}
, mRenderer {Renderer::getInstance()}
, mColor {0x000000FF} , mColor {0x000000FF}
, mBgColor {0x00000000} , mBgColor {0x00000000}
, mColorOpacity {1.0f} , mColorOpacity {1.0f}
@ -161,11 +163,11 @@ void TextComponent::render(const glm::mat4& parentTrans)
return; return;
glm::mat4 trans {parentTrans * getTransform()}; glm::mat4 trans {parentTrans * getTransform()};
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
if (mRenderBackground) if (mRenderBackground)
Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, mBgColor, mBgColor, false, mRenderer->drawRect(0.0f, 0.0f, mSize.x, mSize.y, mBgColor, mBgColor, false,
mOpacity * mThemeOpacity, mDimming); mOpacity * mThemeOpacity, mDimming);
if (mTextCache) { if (mTextCache) {
const glm::vec2& textSize {mTextCache->metrics.size}; const glm::vec2& textSize {mTextCache->metrics.size};
@ -191,29 +193,29 @@ void TextComponent::render(const glm::mat4& parentTrans)
// Draw the "textbox" area, what we are aligned within. // Draw the "textbox" area, what we are aligned within.
if (Settings::getInstance()->getBool("DebugText")) if (Settings::getInstance()->getBool("DebugText"))
Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0x0000FF33, 0x0000FF33); mRenderer->drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0x0000FF33, 0x0000FF33);
trans = glm::translate(trans, off); trans = glm::translate(trans, off);
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
// Draw the text area, where the text actually is located. // Draw the text area, where the text actually is located.
if (Settings::getInstance()->getBool("DebugText")) { if (Settings::getInstance()->getBool("DebugText")) {
switch (mHorizontalAlignment) { switch (mHorizontalAlignment) {
case ALIGN_LEFT: { case ALIGN_LEFT: {
Renderer::drawRect(0.0f, 0.0f, mTextCache->metrics.size.x, mRenderer->drawRect(0.0f, 0.0f, mTextCache->metrics.size.x,
mTextCache->metrics.size.y, 0x00000033, 0x00000033); mTextCache->metrics.size.y, 0x00000033, 0x00000033);
break; break;
} }
case ALIGN_CENTER: { case ALIGN_CENTER: {
Renderer::drawRect((mSize.x - mTextCache->metrics.size.x) / 2.0f, 0.0f, mRenderer->drawRect((mSize.x - mTextCache->metrics.size.x) / 2.0f, 0.0f,
mTextCache->metrics.size.x, mTextCache->metrics.size.y, mTextCache->metrics.size.x, mTextCache->metrics.size.y,
0x00000033, 0x00000033); 0x00000033, 0x00000033);
break; break;
} }
case ALIGN_RIGHT: { case ALIGN_RIGHT: {
Renderer::drawRect(mSize.x - mTextCache->metrics.size.x, 0.0f, mRenderer->drawRect(mSize.x - mTextCache->metrics.size.x, 0.0f,
mTextCache->metrics.size.x, mTextCache->metrics.size.y, mTextCache->metrics.size.x, mTextCache->metrics.size.y,
0x00000033, 0x00000033); 0x00000033, 0x00000033);
break; break;
} }
default: { default: {

View file

@ -89,6 +89,7 @@ private:
void calculateExtent(); void calculateExtent();
void onColorChanged(); void onColorChanged();
Renderer* mRenderer;
unsigned int mColor; unsigned int mColor;
unsigned int mBgColor; unsigned int mBgColor;
float mColorOpacity; float mColorOpacity;

View file

@ -19,7 +19,8 @@
#define BLINKTIME 1000 #define BLINKTIME 1000
TextEditComponent::TextEditComponent() TextEditComponent::TextEditComponent()
: mFocused {false} : mRenderer {Renderer::getInstance()}
, mFocused {false}
, mEditing {false} , mEditing {false}
, mCursor {0} , mCursor {0}
, mBlinkTime {0} , mBlinkTime {0}
@ -304,16 +305,16 @@ void TextEditComponent::render(const glm::mat4& parentTrans)
glm::ivec2 clipDim {static_cast<int>(dimScaled.x - trans[3].x), glm::ivec2 clipDim {static_cast<int>(dimScaled.x - trans[3].x),
static_cast<int>(dimScaled.y - trans[3].y)}; static_cast<int>(dimScaled.y - trans[3].y)};
Renderer::pushClipRect(clipPos, clipDim); mRenderer->pushClipRect(clipPos, clipDim);
trans = glm::translate(trans, glm::vec3 {-mScrollOffset.x, -mScrollOffset.y, 0.0f}); trans = glm::translate(trans, glm::vec3 {-mScrollOffset.x, -mScrollOffset.y, 0.0f});
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
if (mTextCache) if (mTextCache)
mFont->renderTextCache(mTextCache.get()); mFont->renderTextCache(mTextCache.get());
// Pop the clip early to allow the cursor to be drawn outside of the "text area". // Pop the clip early to allow the cursor to be drawn outside of the "text area".
Renderer::popClipRect(); mRenderer->popClipRect();
// Draw cursor. // Draw cursor.
glm::vec2 cursorPos; glm::vec2 cursorPos;
@ -328,15 +329,15 @@ void TextEditComponent::render(const glm::mat4& parentTrans)
float cursorHeight = mFont->getHeight() * 0.8f; float cursorHeight = mFont->getHeight() * 0.8f;
if (!mEditing) { if (!mEditing) {
Renderer::drawRect(cursorPos.x, cursorPos.y + (mFont->getHeight() - cursorHeight) / 2.0f, mRenderer->drawRect(cursorPos.x, cursorPos.y + (mFont->getHeight() - cursorHeight) / 2.0f,
2.0f * Renderer::getScreenWidthModifier(), cursorHeight, 0xC7C7C7FF, 2.0f * Renderer::getScreenWidthModifier(), cursorHeight, 0xC7C7C7FF,
0xC7C7C7FF); 0xC7C7C7FF);
} }
if (mEditing && mBlinkTime < BLINKTIME / 2) { if (mEditing && mBlinkTime < BLINKTIME / 2) {
Renderer::drawRect(cursorPos.x, cursorPos.y + (mFont->getHeight() - cursorHeight) / 2.0f, mRenderer->drawRect(cursorPos.x, cursorPos.y + (mFont->getHeight() - cursorHeight) / 2.0f,
2.0f * Renderer::getScreenWidthModifier(), cursorHeight, 0x777777FF, 2.0f * Renderer::getScreenWidthModifier(), cursorHeight, 0x777777FF,
0x777777FF); 0x777777FF);
} }
} }

View file

@ -56,6 +56,7 @@ private:
glm::vec2 getTextAreaPos() const; glm::vec2 getTextAreaPos() const;
glm::vec2 getTextAreaSize() const; glm::vec2 getTextAreaSize() const;
Renderer* mRenderer;
std::string mText; std::string mText;
std::string mTextOrig; std::string mTextOrig;
bool mFocused; bool mFocused;

View file

@ -135,6 +135,7 @@ protected:
void onCursorChanged(const CursorState& state) override; void onCursorChanged(const CursorState& state) override;
private: private:
Renderer* mRenderer;
int mLoopOffset; int mLoopOffset;
int mLoopOffset2; int mLoopOffset2;
int mLoopTime; int mLoopTime;
@ -164,6 +165,7 @@ private:
template <typename T> TextListComponent<T>::TextListComponent() template <typename T> TextListComponent<T>::TextListComponent()
{ {
mRenderer = Renderer::getInstance();
mLoopOffset = 0; mLoopOffset = 0;
mLoopOffset2 = 0; mLoopOffset2 = 0;
mLoopTime = 0; mLoopTime = 0;
@ -232,17 +234,17 @@ template <typename T> void TextListComponent<T>::render(const glm::mat4& parentT
mSelectorImage.render(trans); mSelectorImage.render(trans);
} }
else { else {
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
Renderer::drawRect(0.0f, (mCursor - startEntry) * entrySize + mSelectorOffsetY, mSize.x, mRenderer->drawRect(0.0f, (mCursor - startEntry) * entrySize + mSelectorOffsetY,
mSelectorHeight, mSelectorColor, mSelectorColorEnd, mSize.x, mSelectorHeight, mSelectorColor, mSelectorColorEnd,
mSelectorColorGradientHorizontal); mSelectorColorGradientHorizontal);
} }
} }
if (Settings::getInstance()->getBool("DebugText")) { if (Settings::getInstance()->getBool("DebugText")) {
Renderer::drawRect(mHorizontalMargin, 0.0f, mSize.x - mHorizontalMargin * 2.0f, mSize.y, mRenderer->drawRect(mHorizontalMargin, 0.0f, mSize.x - mHorizontalMargin * 2.0f, mSize.y,
0x00000033, 0x00000033); 0x00000033, 0x00000033);
Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0x0000FF33, 0x0000FF33); mRenderer->drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0x0000FF33, 0x0000FF33);
} }
// Clip to inside margins. // Clip to inside margins.
@ -250,7 +252,7 @@ template <typename T> void TextListComponent<T>::render(const glm::mat4& parentT
dim.x = (trans[0].x * dim.x + trans[3].x) - trans[3].x; dim.x = (trans[0].x * dim.x + trans[3].x) - trans[3].x;
dim.y = (trans[1].y * dim.y + trans[3].y) - trans[3].y; dim.y = (trans[1].y * dim.y + trans[3].y) - trans[3].y;
Renderer::pushClipRect( mRenderer->pushClipRect(
glm::ivec2 {static_cast<int>(std::round(trans[3].x + mHorizontalMargin)), glm::ivec2 {static_cast<int>(std::round(trans[3].x + mHorizontalMargin)),
static_cast<int>(std::round(trans[3].y))}, static_cast<int>(std::round(trans[3].y))},
glm::ivec2 {static_cast<int>(std::round(dim.x - mHorizontalMargin * 2.0f)), glm::ivec2 {static_cast<int>(std::round(dim.x - mHorizontalMargin * 2.0f)),
@ -323,7 +325,7 @@ template <typename T> void TextListComponent<T>::render(const glm::mat4& parentT
if (mLoopOffset == 0 && mLoopOffset2 == 0) if (mLoopOffset == 0 && mLoopOffset2 == 0)
mLoopScroll = false; mLoopScroll = false;
Renderer::setMatrix(drawTrans); mRenderer->setMatrix(drawTrans);
font->renderTextCache(entry.data.textCache.get()); font->renderTextCache(entry.data.textCache.get());
// Render currently selected row again if text is moved far enough for it to repeat. // Render currently selected row again if text is moved far enough for it to repeat.
@ -332,12 +334,12 @@ template <typename T> void TextListComponent<T>::render(const glm::mat4& parentT
drawTrans = trans; drawTrans = trans;
drawTrans = glm::translate( drawTrans = glm::translate(
drawTrans, offset - glm::vec3 {static_cast<float>(mLoopOffset2), 0.0f, 0.0f}); drawTrans, offset - glm::vec3 {static_cast<float>(mLoopOffset2), 0.0f, 0.0f});
Renderer::setMatrix(drawTrans); mRenderer->setMatrix(drawTrans);
font->renderTextCache(entry.data.textCache.get()); font->renderTextCache(entry.data.textCache.get());
} }
y += entrySize; y += entrySize;
} }
Renderer::popClipRect(); mRenderer->popClipRect();
List::listRenderTitleOverlay(trans); List::listRenderTitleOverlay(trans);
GuiComponent::renderChildren(trans); GuiComponent::renderChildren(trans);
} }

View file

@ -15,6 +15,8 @@
#include "Window.h" #include "Window.h"
#include "resources/TextureResource.h" #include "resources/TextureResource.h"
#include <SDL2/SDL.h>
#include <algorithm> #include <algorithm>
#include <iomanip> #include <iomanip>
@ -24,7 +26,8 @@ std::vector<std::string> VideoFFmpegComponent::sHWDecodedVideos;
std::vector<std::string> VideoFFmpegComponent::sSWDecodedVideos; std::vector<std::string> VideoFFmpegComponent::sSWDecodedVideos;
VideoFFmpegComponent::VideoFFmpegComponent() VideoFFmpegComponent::VideoFFmpegComponent()
: mRectangleOffset {0.0f, 0.0f} : mRenderer {Renderer::getInstance()}
, mRectangleOffset {0.0f, 0.0f}
, mFrameProcessingThread {nullptr} , mFrameProcessingThread {nullptr}
, mFormatContext {nullptr} , mFormatContext {nullptr}
, mVideoStream {nullptr} , mVideoStream {nullptr}
@ -133,7 +136,7 @@ void VideoFFmpegComponent::render(const glm::mat4& parentTrans)
if (mIsPlaying && mFormatContext) { if (mIsPlaying && mFormatContext) {
Renderer::Vertex vertices[4]; Renderer::Vertex vertices[4];
Renderer::setMatrix(parentTrans); mRenderer->setMatrix(parentTrans);
unsigned int rectColor {0x000000FF}; unsigned int rectColor {0x000000FF};
@ -142,9 +145,9 @@ void VideoFFmpegComponent::render(const glm::mat4& parentTrans)
// Render the black rectangle behind the video. // Render the black rectangle behind the video.
if (mVideoRectangleCoords.size() == 4) { if (mVideoRectangleCoords.size() == 4) {
Renderer::drawRect(mVideoRectangleCoords[0], mVideoRectangleCoords[1], mRenderer->drawRect(mVideoRectangleCoords[0], mVideoRectangleCoords[1],
mVideoRectangleCoords[2], mVideoRectangleCoords[3], // Line break. mVideoRectangleCoords[2], mVideoRectangleCoords[3], // Line break.
rectColor, rectColor); rectColor, rectColor);
} }
// This is needed to avoid a slight gap before the video starts playing. // This is needed to avoid a slight gap before the video starts playing.
@ -219,8 +222,8 @@ void VideoFFmpegComponent::render(const glm::mat4& parentTrans)
} }
// Render it. // Render it.
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
Renderer::drawTriangleStrips(&vertices[0], 4); mRenderer->drawTriangleStrips(&vertices[0], 4);
} }
else { else {
if (mVisible) if (mVisible)

View file

@ -84,6 +84,7 @@ private:
static void detectHWDecoder(); static void detectHWDecoder();
bool decoderInitHW(); bool decoderInitHW();
Renderer* mRenderer;
static enum AVHWDeviceType sDeviceType; static enum AVHWDeviceType sDeviceType;
static enum AVPixelFormat sPixelFormat; static enum AVPixelFormat sPixelFormat;
static std::vector<std::string> sSWDecodedVideos; static std::vector<std::string> sSWDecodedVideos;

View file

@ -15,7 +15,8 @@
#include <SDL2/SDL_timer.h> #include <SDL2/SDL_timer.h>
GuiInfoPopup::GuiInfoPopup(std::string message, int duration) GuiInfoPopup::GuiInfoPopup(std::string message, int duration)
: mMessage {message} : mRenderer {Renderer::getInstance()}
, mMessage {message}
, mDuration {duration} , mDuration {duration}
, mAlpha {1.0f} , mAlpha {1.0f}
, mRunning {true} , mRunning {true}
@ -78,7 +79,7 @@ void GuiInfoPopup::render(const glm::mat4& /*parentTrans*/)
glm::mat4 trans {getTransform() * Renderer::getIdentity()}; glm::mat4 trans {getTransform() * Renderer::getIdentity()};
if (mRunning && updateState()) { if (mRunning && updateState()) {
// If we're still supposed to be rendering it. // If we're still supposed to be rendering it.
Renderer::setMatrix(trans); mRenderer->setMatrix(trans);
renderChildren(trans); renderChildren(trans);
} }
} }

View file

@ -10,6 +10,7 @@
#define ES_APP_GUIS_GUI_INFO_POPUP_H #define ES_APP_GUIS_GUI_INFO_POPUP_H
#include "GuiComponent.h" #include "GuiComponent.h"
#include "renderers/Renderer.h"
class ComponentGrid; class ComponentGrid;
class NinePatchComponent; class NinePatchComponent;
@ -27,6 +28,7 @@ public:
private: private:
bool updateState(); bool updateState();
Renderer* mRenderer;
ComponentGrid* mGrid; ComponentGrid* mGrid;
NinePatchComponent* mFrame; NinePatchComponent* mFrame;

View file

@ -3,7 +3,7 @@
// EmulationStation Desktop Edition // EmulationStation Desktop Edition
// Renderer.cpp // Renderer.cpp
// //
// General rendering functions. // Generic rendering functions.
// //
#include "renderers/Renderer.h" #include "renderers/Renderer.h"
@ -12,468 +12,386 @@
#include "Log.h" #include "Log.h"
#include "Settings.h" #include "Settings.h"
#include "Shader_GL21.h" #include "Shader_GL21.h"
#include "renderers/Renderer_GL21.h"
#include "resources/ResourceManager.h" #include "resources/ResourceManager.h"
#include <SDL2/SDL.h>
#include <stack>
#if defined(_WIN64) #if defined(_WIN64)
#include <windows.h> #include <windows.h>
#endif #endif
namespace Renderer Renderer* Renderer::getInstance()
{ {
static std::stack<Rect> clipStack; static RendererOpenGL instance;
static SDL_Window* sdlWindow {nullptr}; return &instance;
static glm::mat4 mProjectionMatrix {}; }
static glm::mat4 mProjectionMatrixRotated {};
static int windowWidth {0};
static int windowHeight {0};
static int screenWidth {0};
static int screenHeight {0};
static int screenOffsetX {0};
static int screenOffsetY {0};
static bool screenRotated {0};
static bool initialCursorState {1};
// Screen resolution modifiers relative to the 1920x1080 reference.
static float screenHeightModifier {0.0f};
static float screenWidthModifier {0.0f};
static float screenAspectRatio {0.0f};
static void setIcon() void Renderer::setIcon()
{ {
size_t width {0}; size_t width {0};
size_t height {0}; size_t height {0};
ResourceData resData { ResourceData resData {
ResourceManager::getInstance().getFileData(":/graphics/window_icon_256.png")}; ResourceManager::getInstance().getFileData(":/graphics/window_icon_256.png")};
std::vector<unsigned char> rawData { std::vector<unsigned char> rawData {
ImageIO::loadFromMemoryRGBA32(resData.ptr.get(), resData.length, width, height)}; ImageIO::loadFromMemoryRGBA32(resData.ptr.get(), resData.length, width, height)};
if (!rawData.empty()) { if (!rawData.empty()) {
ImageIO::flipPixelsVert(rawData.data(), width, height); ImageIO::flipPixelsVert(rawData.data(), width, height);
#if SDL_BYTEORDER == SDL_BIG_ENDIAN #if SDL_BYTEORDER == SDL_BIG_ENDIAN
unsigned int rmask {0xFF000000}; unsigned int rmask {0xFF000000};
unsigned int gmask {0x00FF0000}; unsigned int gmask {0x00FF0000};
unsigned int bmask {0x0000FF00}; unsigned int bmask {0x0000FF00};
unsigned int amask {0x000000FF}; unsigned int amask {0x000000FF};
#else #else
unsigned int rmask {0x000000FF}; unsigned int rmask {0x000000FF};
unsigned int gmask {0x0000FF00}; unsigned int gmask {0x0000FF00};
unsigned int bmask {0x00FF0000}; unsigned int bmask {0x00FF0000};
unsigned int amask {0xFF000000}; unsigned int amask {0xFF000000};
#endif #endif
// Try creating SDL surface from logo data. // Try creating SDL surface from logo data.
SDL_Surface* logoSurface {SDL_CreateRGBSurfaceFrom( SDL_Surface* logoSurface {SDL_CreateRGBSurfaceFrom(
static_cast<void*>(rawData.data()), static_cast<int>(width), static_cast<void*>(rawData.data()), static_cast<int>(width), static_cast<int>(height),
static_cast<int>(height), 32, static_cast<int>((width * 4)), rmask, gmask, bmask, 32, static_cast<int>((width * 4)), rmask, gmask, bmask, amask)};
amask)};
if (logoSurface != nullptr) { if (logoSurface != nullptr) {
SDL_SetWindowIcon(sdlWindow, logoSurface); SDL_SetWindowIcon(mSDLWindow, logoSurface);
SDL_FreeSurface(logoSurface); SDL_FreeSurface(logoSurface);
}
} }
} }
}
static bool createWindow() bool Renderer::createWindow()
{ {
LOG(LogInfo) << "Creating window..."; LOG(LogInfo) << "Creating window...";
if (SDL_Init(SDL_INIT_VIDEO) != 0) { if (SDL_Init(SDL_INIT_VIDEO) != 0) {
LOG(LogError) << "Couldn't initialize SDL: " << SDL_GetError(); LOG(LogError) << "Couldn't initialize SDL: " << SDL_GetError();
return false; return false;
} }
initialCursorState = (SDL_ShowCursor(0) != 0); mInitialCursorState = (SDL_ShowCursor(0) != 0);
int displayIndex {Settings::getInstance()->getInt("DisplayIndex")}; int displayIndex {Settings::getInstance()->getInt("DisplayIndex")};
// Check that an invalid value has not been manually entered in the es_settings.xml file. // Check that an invalid value has not been manually entered in the es_settings.xml file.
if (displayIndex != 1 && displayIndex != 2 && displayIndex != 3 && displayIndex != 4) { if (displayIndex != 1 && displayIndex != 2 && displayIndex != 3 && displayIndex != 4) {
Settings::getInstance()->setInt("DisplayIndex", 1); Settings::getInstance()->setInt("DisplayIndex", 1);
displayIndex = 0; displayIndex = 0;
} }
else { else {
--displayIndex; --displayIndex;
} }
int availableDisplays = SDL_GetNumVideoDisplays(); int availableDisplays = SDL_GetNumVideoDisplays();
if (displayIndex > availableDisplays - 1) { if (displayIndex > availableDisplays - 1) {
LOG(LogWarning) << "Requested display " << std::to_string(displayIndex + 1) LOG(LogWarning) << "Requested display " << std::to_string(displayIndex + 1)
<< " does not exist, changing to display 1"; << " does not exist, changing to display 1";
displayIndex = 0; displayIndex = 0;
} }
else { else {
LOG(LogInfo) << "Using display: " << std::to_string(displayIndex + 1); LOG(LogInfo) << "Using display: " << std::to_string(displayIndex + 1);
} }
SDL_DisplayMode displayMode; SDL_DisplayMode displayMode;
SDL_GetDesktopDisplayMode(displayIndex, &displayMode); SDL_GetDesktopDisplayMode(displayIndex, &displayMode);
#if defined(_WIN64) #if defined(_WIN64)
// Tell Windows that we're DPI aware so that we can set a physical resolution and // Tell Windows that we're DPI aware so that we can set a physical resolution and
// avoid any automatic DPI scaling. // avoid any automatic DPI scaling.
SetProcessDPIAware(); SetProcessDPIAware();
// We need to set the resolution based on the actual display bounds as the numbers // We need to set the resolution based on the actual display bounds as the numbers
// returned by SDL_GetDesktopDisplayMode are calculated based on DPI scaling and // returned by SDL_GetDesktopDisplayMode are calculated based on DPI scaling and
// therefore do not necessarily reflect the physical display resolution. // therefore do not necessarily reflect the physical display resolution.
SDL_Rect displayBounds; SDL_Rect displayBounds;
SDL_GetDisplayBounds(displayIndex, &displayBounds); SDL_GetDisplayBounds(displayIndex, &displayBounds);
displayMode.w = displayBounds.w; displayMode.w = displayBounds.w;
displayMode.h = displayBounds.h; displayMode.h = displayBounds.h;
#endif #endif
windowWidth = Settings::getInstance()->getInt("WindowWidth") ? mWindowWidth = Settings::getInstance()->getInt("WindowWidth") ?
Settings::getInstance()->getInt("WindowWidth") : Settings::getInstance()->getInt("WindowWidth") :
displayMode.w; displayMode.w;
windowHeight = Settings::getInstance()->getInt("WindowHeight") ? mWindowHeight = Settings::getInstance()->getInt("WindowHeight") ?
Settings::getInstance()->getInt("WindowHeight") : Settings::getInstance()->getInt("WindowHeight") :
displayMode.h; displayMode.h;
screenWidth = Settings::getInstance()->getInt("ScreenWidth") ? sScreenWidth = Settings::getInstance()->getInt("ScreenWidth") ?
Settings::getInstance()->getInt("ScreenWidth") : Settings::getInstance()->getInt("ScreenWidth") :
windowWidth; mWindowWidth;
screenHeight = Settings::getInstance()->getInt("ScreenHeight") ? sScreenHeight = Settings::getInstance()->getInt("ScreenHeight") ?
Settings::getInstance()->getInt("ScreenHeight") : Settings::getInstance()->getInt("ScreenHeight") :
windowHeight; mWindowHeight;
screenOffsetX = Settings::getInstance()->getInt("ScreenOffsetX") ? mScreenOffsetX = Settings::getInstance()->getInt("ScreenOffsetX") ?
Settings::getInstance()->getInt("ScreenOffsetX") : Settings::getInstance()->getInt("ScreenOffsetX") :
0; 0;
screenOffsetY = Settings::getInstance()->getInt("ScreenOffsetY") ? mScreenOffsetY = Settings::getInstance()->getInt("ScreenOffsetY") ?
Settings::getInstance()->getInt("ScreenOffsetY") : Settings::getInstance()->getInt("ScreenOffsetY") :
0; 0;
screenRotated = Settings::getInstance()->getBool("ScreenRotate"); mScreenRotated = Settings::getInstance()->getBool("ScreenRotate");
// Prevent the application window from minimizing when switching windows (when launching // Prevent the application window from minimizing when switching windows (when launching
// games or when manually switching windows using the task switcher). // games or when manually switching windows using the task switcher).
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
#if defined(__unix__) #if defined(__unix__)
// Disabling desktop composition can lead to better framerates and a more fluid user // Disabling desktop composition can lead to better framerates and a more fluid user
// interface, but with some drivers it can cause strange behaviors when returning to // interface, but with some drivers it can cause strange behaviors when returning to
// the desktop. // the desktop.
if (Settings::getInstance()->getBool("DisableComposition")) if (Settings::getInstance()->getBool("DisableComposition"))
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "1"); SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "1");
else else
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0"); SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
#endif #endif
bool userResolution = false; bool userResolution = false;
// Check if the user has changed the resolution from the command line. // Check if the user has changed the resolution from the command line.
if (windowWidth != displayMode.w || windowHeight != displayMode.h) if (mWindowWidth != displayMode.w || mWindowHeight != displayMode.h)
userResolution = true; userResolution = true;
unsigned int windowFlags; unsigned int windowFlags;
setupWindow(); setup();
#if defined(_WIN64) #if defined(_WIN64)
// For Windows we use SDL_WINDOW_BORDERLESS as "real" full screen doesn't work properly. // For Windows we use SDL_WINDOW_BORDERLESS as "real" full screen doesn't work properly.
// The borderless mode seems to behave well and it's almost completely seamless, especially // The borderless mode seems to behave well and it's almost completely seamless, especially
// with a hidden taskbar. // with a hidden taskbar.
if (!userResolution) if (!userResolution)
windowFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_OPENGL; windowFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_OPENGL;
else else
// If the resolution has been manually set from the command line, then keep the border. // If the resolution has been manually set from the command line, then keep the border.
windowFlags = SDL_WINDOW_OPENGL; windowFlags = SDL_WINDOW_OPENGL;
#elif defined(__APPLE__) #elif defined(__APPLE__)
// Not sure if this could be a useful setting. // Not sure if this could be a useful setting.
// SDL_SetHint(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, "0"); // SDL_SetHint(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, "0");
// The SDL_WINDOW_BORDERLESS mode seems to be the only mode that somehow works on macOS // The SDL_WINDOW_BORDERLESS mode seems to be the only mode that somehow works on macOS
// as a real fullscreen mode will do lots of weird stuff like preventing window switching // as a real fullscreen mode will do lots of weird stuff like preventing window switching
// or refusing to let emulators run at all. SDL_WINDOW_FULLSCREEN_DESKTOP almost works, but // or refusing to let emulators run at all. SDL_WINDOW_FULLSCREEN_DESKTOP almost works, but
// it "shuffles" windows when starting the emulator and won't return properly when the game // it "shuffles" windows when starting the emulator and won't return properly when the game
// has exited. With SDL_WINDOW_BORDERLESS some emulators (like RetroArch) have to be // has exited. With SDL_WINDOW_BORDERLESS some emulators (like RetroArch) have to be
// configured to run in fullscreen mode or switching to its window will not work, but // configured to run in fullscreen mode or switching to its window will not work, but
// apart from that this mode works fine. // apart from that this mode works fine.
if (!userResolution) if (!userResolution)
windowFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_OPENGL; windowFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_OPENGL;
else else
windowFlags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_OPENGL; windowFlags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_OPENGL;
#else #else
if (!userResolution) if (!userResolution)
windowFlags = SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_OPENGL; windowFlags = SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_OPENGL;
else else
windowFlags = SDL_WINDOW_OPENGL; windowFlags = SDL_WINDOW_OPENGL;
#endif #endif
if ((sdlWindow = if ((mSDLWindow =
SDL_CreateWindow("EmulationStation", SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), SDL_CreateWindow("EmulationStation", SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex),
SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), windowWidth, SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), mWindowWidth,
windowHeight, windowFlags)) == nullptr) { mWindowHeight, windowFlags)) == nullptr) {
LOG(LogError) << "Couldn't create SDL window. " << SDL_GetError(); LOG(LogError) << "Couldn't create SDL window. " << SDL_GetError();
return false; return false;
} }
#if defined(__APPLE__) #if defined(__APPLE__)
// The code below is required as the high DPI scaling on macOS is very bizarre and is // The code below is required as the high DPI scaling on macOS is very bizarre and is
// measured in "points" rather than pixels (even though the naming convention sure looks // measured in "points" rather than pixels (even though the naming convention sure looks
// like pixels). For example there could be a 1920x1080 entry in the OS display settings // like pixels). For example there could be a 1920x1080 entry in the OS display settings
// that actually corresponds to something like 3840x2160 pixels while at the same time // that actually corresponds to something like 3840x2160 pixels while at the same time
// there is a separate 1080p entry which corresponds to a "real" 1920x1080 resolution. // there is a separate 1080p entry which corresponds to a "real" 1920x1080 resolution.
// Therefore the --resolution flag results in different things depending on whether a high // Therefore the --resolution flag results in different things depending on whether a high
// DPI screen is used. E.g. 1280x720 on a 4K display would actually end up as 2560x1440 // DPI screen is used. E.g. 1280x720 on a 4K display would actually end up as 2560x1440
// which is incredibly strange. No point in struggling with this strangeness though, // which is incredibly strange. No point in struggling with this strangeness though,
// instead we simply indicate the physical pixel dimensions in parenthesis in the log // instead we simply indicate the physical pixel dimensions in parenthesis in the log
// file and make sure to double the window and screen sizes in case of a high DPI // file and make sure to double the window and screen sizes in case of a high DPI
// display so that the full application window is used for rendering. // display so that the full application window is used for rendering.
int width = 0; int width = 0;
SDL_GL_GetDrawableSize(sdlWindow, &width, nullptr); SDL_GL_GetDrawableSize(mSDLWindow, &width, nullptr);
int scaleFactor = static_cast<int>(width / windowWidth); int scaleFactor = static_cast<int>(width / mWindowWidth);
LOG(LogInfo) << "Display resolution: " << std::to_string(displayMode.w) << "x" LOG(LogInfo) << "Display resolution: " << std::to_string(displayMode.w) << "x"
<< std::to_string(displayMode.h) << " (physical resolution " << std::to_string(displayMode.h) << " (physical resolution "
<< std::to_string(displayMode.w * scaleFactor) << "x" << std::to_string(displayMode.w * scaleFactor) << "x"
<< std::to_string(displayMode.h * scaleFactor) << ")"; << std::to_string(displayMode.h * scaleFactor) << ")";
LOG(LogInfo) << "Display refresh rate: " << std::to_string(displayMode.refresh_rate) LOG(LogInfo) << "Display refresh rate: " << std::to_string(displayMode.refresh_rate) << " Hz";
<< " Hz"; LOG(LogInfo) << "EmulationStation resolution: " << std::to_string(mWindowWidth) << "x"
LOG(LogInfo) << "EmulationStation resolution: " << std::to_string(windowWidth) << "x" << std::to_string(mWindowHeight) << " (physical resolution "
<< std::to_string(windowHeight) << " (physical resolution " << std::to_string(mWindowWidth * scaleFactor) << "x"
<< std::to_string(windowWidth * scaleFactor) << "x" << std::to_string(mWindowHeight * scaleFactor) << ")";
<< std::to_string(windowHeight * scaleFactor) << ")";
windowWidth *= scaleFactor; mWindowWidth *= scaleFactor;
windowHeight *= scaleFactor; mWindowHeight *= scaleFactor;
screenWidth *= scaleFactor; sScreenWidth *= scaleFactor;
screenHeight *= scaleFactor; sScreenHeight *= scaleFactor;
#else #else
LOG(LogInfo) << "Display resolution: " << std::to_string(displayMode.w) << "x" LOG(LogInfo) << "Display resolution: " << std::to_string(displayMode.w) << "x"
<< std::to_string(displayMode.h); << std::to_string(displayMode.h);
LOG(LogInfo) << "Display refresh rate: " << std::to_string(displayMode.refresh_rate) LOG(LogInfo) << "Display refresh rate: " << std::to_string(displayMode.refresh_rate) << " Hz";
<< " Hz"; LOG(LogInfo) << "EmulationStation resolution: " << std::to_string(mWindowWidth) << "x"
LOG(LogInfo) << "EmulationStation resolution: " << std::to_string(windowWidth) << "x" << std::to_string(mWindowHeight);
<< std::to_string(windowHeight);
#endif #endif
screenHeightModifier = static_cast<float>(screenHeight) / 1080.0f; sScreenHeightModifier = static_cast<float>(sScreenHeight) / 1080.0f;
screenWidthModifier = static_cast<float>(screenWidth) / 1920.0f; sScreenWidthModifier = static_cast<float>(sScreenWidth) / 1920.0f;
screenAspectRatio = static_cast<float>(screenWidth) / static_cast<float>(screenHeight); sScreenAspectRatio = static_cast<float>(sScreenWidth) / static_cast<float>(sScreenHeight);
LOG(LogInfo) << "Setting up OpenGL..."; LOG(LogInfo) << "Setting up OpenGL...";
if (!createContext()) if (!createContext())
return false; return false;
setIcon(); setIcon();
setSwapInterval(); setSwapInterval();
#if defined(_WIN64) #if defined(_WIN64)
// It seems as if Windows needs this to avoid a brief white screen flash on startup. // It seems as if Windows needs this to avoid a brief white screen flash on startup.
// Possibly this is driver-specific rather than OS-specific. There is additional code // Possibly this is driver-specific rather than OS-specific. There is additional code
// in init() to work around the white screen flash issue on all operating systems. // in init() to work around the white screen flash issue on all operating systems.
swapBuffers(); swapBuffers();
#endif #endif
LOG(LogInfo) << "Loading shaders..."; return loadShaders();
}
std::vector<std::string> shaderFiles; void Renderer::destroyWindow()
shaderFiles.push_back(":/shaders/glsl/core.glsl"); {
shaderFiles.push_back(":/shaders/glsl/blur_horizontal.glsl"); destroyContext();
shaderFiles.push_back(":/shaders/glsl/blur_vertical.glsl"); SDL_DestroyWindow(mSDLWindow);
shaderFiles.push_back(":/shaders/glsl/scanlines.glsl");
for (auto it = shaderFiles.cbegin(); it != shaderFiles.cend(); ++it) { mSDLWindow = nullptr;
Shader* loadShader = new Shader();
loadShader->loadShaderFile(*it, GL_VERTEX_SHADER); SDL_ShowCursor(mInitialCursorState);
loadShader->loadShaderFile(*it, GL_FRAGMENT_SHADER); SDL_Quit();
}
if (!loadShader->createProgram()) { bool Renderer::init()
LOG(LogError) << "Could not create shader program."; {
return false; if (!createWindow())
} return false;
sShaderProgramVector.push_back(loadShader); glm::mat4 projection {getIdentity()};
} Rect viewport {0, 0, 0, 0};
return true; viewport.x = mWindowWidth - mScreenOffsetX - sScreenWidth;
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});
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()),
static_cast<float>(getScreenHeight()), 0x000000FF, 0x000000FF);
swapBuffers();
return true;
}
void Renderer::deinit()
{
// Destroy the window.
destroyWindow();
}
void Renderer::pushClipRect(const glm::ivec2& pos, const glm::ivec2& size)
{
Rect box {pos.x, pos.y, size.x, size.y};
if (box.w == 0)
box.w = sScreenWidth - box.x;
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);
}
else {
box = Rect(mScreenOffsetX + box.x, mScreenOffsetY + box.y, box.w, box.h);
} }
static void destroyWindow() // Make sure the box fits within mClipStack.top(), and clip further accordingly.
{ if (mClipStack.size()) {
for (auto it = sShaderProgramVector.cbegin(); it != sShaderProgramVector.cend(); ++it) const Rect& top {mClipStack.top()};
delete *it; if (top.x > box.x)
box.x = top.x;
destroyContext(); if (top.y > box.y)
SDL_DestroyWindow(sdlWindow); box.y = top.y;
if ((top.x + top.w) < (box.x + box.w))
sdlWindow = nullptr; box.w = (top.x + top.w) - box.x;
if ((top.y + top.h) < (box.y + box.h))
SDL_ShowCursor(initialCursorState); box.h = (top.y + top.h) - box.y;
SDL_Quit();
} }
bool init() if (box.w < 0)
{ box.w = 0;
if (!createWindow()) if (box.h < 0)
return false; box.h = 0;
glm::mat4 projection {getIdentity()}; mClipStack.push(box);
Rect viewport {0, 0, 0, 0};
viewport.x = windowWidth - screenOffsetX - screenWidth; setScissor(box);
viewport.y = windowHeight - screenOffsetY - screenHeight; }
viewport.w = screenWidth;
viewport.h = screenHeight;
projection = glm::ortho(0.0f, static_cast<float>(screenWidth),
static_cast<float>(screenHeight), 0.0f, -1.0f, 1.0f);
projection = glm::rotate(projection, glm::radians(180.0f), {0.0f, 0.0f, 1.0f});
mProjectionMatrixRotated =
glm::translate(projection, {screenWidth * -1.0f, screenHeight * -1.0f, 0.0f});
viewport.x = screenOffsetX; void Renderer::popClipRect()
viewport.y = screenOffsetY; {
viewport.w = screenWidth; if (mClipStack.empty()) {
viewport.h = screenHeight; LOG(LogError) << "Tried to popClipRect while the stack was empty";
mProjectionMatrix = glm::ortho(0.0f, static_cast<float>(screenWidth), return;
static_cast<float>(screenHeight), 0.0f, -1.0f, 1.0f);
// This is required to avoid a brief white screen flash during startup on some systems.
Renderer::drawRect(0.0f, 0.0f, static_cast<float>(Renderer::getScreenWidth()),
static_cast<float>(Renderer::getScreenHeight()), 0x000000FF, 0x000000FF);
swapBuffers();
return true;
} }
void deinit() mClipStack.pop();
{
// Destroy the window.
destroyWindow();
}
void pushClipRect(const glm::ivec2& pos, const glm::ivec2& size) if (mClipStack.empty())
{ setScissor(Rect(0, 0, 0, 0));
Rect box(pos.x, pos.y, size.x, size.y); else
setScissor(mClipStack.top());
}
if (box.w == 0) void Renderer::drawRect(const float x,
box.w = screenWidth - box.x; const float y,
if (box.h == 0) const float w,
box.h = screenHeight - box.y; const float h,
const unsigned int color,
const unsigned int colorEnd,
bool horizontalGradient,
const float opacity,
const float dimming,
const BlendFactor srcBlendFactorFactor,
const BlendFactor dstBlendFactorFactor)
{
Vertex vertices[4];
if (screenRotated) { float wL {w};
box = Rect(windowWidth - screenOffsetX - box.x - box.w, float hL {h};
windowHeight - screenOffsetY - box.y - box.h, box.w, box.h);
}
else {
box = Rect(screenOffsetX + box.x, screenOffsetY + box.y, box.w, box.h);
}
// Make sure the box fits within clipStack.top(), and clip further accordingly. // If the width or height was scaled down to less than 1 pixel, then set it to
if (clipStack.size()) { // 1 pixel so that it will still render on lower resolutions.
const Rect& top = clipStack.top(); if (wL > 0.0f && wL < 1.0f)
if (top.x > box.x) wL = 1.0f;
box.x = top.x; if (hL > 0.0f && hL < 1.0f)
if (top.y > box.y) hL = 1.0f;
box.y = top.y;
if ((top.x + top.w) < (box.x + box.w))
box.w = (top.x + top.w) - box.x;
if ((top.y + top.h) < (box.y + box.h))
box.h = (top.y + top.h) - box.y;
}
if (box.w < 0) // clang-format off
box.w = 0; vertices[0] = {{x, y }, {0.0f, 0.0f}, color};
if (box.h < 0) vertices[1] = {{x, y + hL}, {0.0f, 0.0f}, horizontalGradient ? color : colorEnd};
box.h = 0; vertices[2] = {{x + wL, y }, {0.0f, 0.0f}, horizontalGradient ? colorEnd : color};
vertices[3] = {{x + wL, y + hL}, {0.0f, 0.0f}, colorEnd};
// clang-format on
clipStack.push(box); // Round vertices.
for (int i = 0; i < 4; ++i)
vertices[i].position = glm::round(vertices[i].position);
setScissor(box); vertices->opacity = opacity;
} vertices->dimming = dimming;
void popClipRect() bindTexture(0);
{ drawTriangleStrips(vertices, 4, srcBlendFactorFactor, dstBlendFactorFactor);
if (clipStack.empty()) { }
LOG(LogError) << "Tried to popClipRect while the stack was empty";
return;
}
clipStack.pop();
if (clipStack.empty())
setScissor(Rect(0, 0, 0, 0));
else
setScissor(clipStack.top());
}
void drawRect(const float x,
const float y,
const float w,
const float h,
const unsigned int color,
const unsigned int colorEnd,
bool horizontalGradient,
const float opacity,
const float dimming,
const Blend::Factor srcBlendFactor,
const Blend::Factor dstBlendFactor)
{
Vertex vertices[4];
float wL {w};
float hL {h};
// If the width or height was scaled down to less than 1 pixel, then set it to
// 1 pixel so that it will still render on lower resolutions.
if (wL > 0.0f && wL < 1.0f)
wL = 1.0f;
if (hL > 0.0f && hL < 1.0f)
hL = 1.0f;
// clang-format off
vertices[0] = {{x, y }, {0.0f, 0.0f}, color};
vertices[1] = {{x, y + hL}, {0.0f, 0.0f}, horizontalGradient ? color : colorEnd};
vertices[2] = {{x + wL, y }, {0.0f, 0.0f}, horizontalGradient ? colorEnd : color};
vertices[3] = {{x + wL, y + hL}, {0.0f, 0.0f}, colorEnd};
// clang-format on
// Round vertices.
for (int i = 0; i < 4; ++i)
vertices[i].position = glm::round(vertices[i].position);
vertices->opacity = opacity;
vertices->dimming = dimming;
bindTexture(0);
drawTriangleStrips(vertices, 4, srcBlendFactor, dstBlendFactor);
}
Shader* getShaderProgram(unsigned int shaderID)
{
unsigned int index = 0;
// Find the index in sShaderProgramVector by counting the number
// of shifts required to reach 0.
while (shaderID > 0) {
shaderID = shaderID >> 1;
++index;
}
if (sShaderProgramVector.size() > index - 1)
return sShaderProgramVector[index - 1];
else
return nullptr;
}
const glm::mat4& getProjectionMatrix()
{
if (screenRotated)
return mProjectionMatrixRotated;
else
return mProjectionMatrix;
}
const glm::mat4& getProjectionMatrixNormal() { return mProjectionMatrix; }
SDL_Window* getSDLWindow() { return sdlWindow; }
const float getWindowWidth() { return static_cast<float>(windowWidth); }
const float getWindowHeight() { return static_cast<float>(windowHeight); }
const float getScreenWidth() { return static_cast<float>(screenWidth); }
const float getScreenHeight() { return static_cast<float>(screenHeight); }
const float getScreenOffsetX() { return static_cast<float>(screenOffsetX); }
const float getScreenOffsetY() { return static_cast<float>(screenOffsetY); }
const bool getScreenRotated() { return screenRotated; }
const float getScreenWidthModifier() { return screenWidthModifier; }
const float getScreenHeightModifier() { return screenHeightModifier; }
const float getScreenAspectRatio() { return screenAspectRatio; }
} // namespace Renderer

View file

@ -3,123 +3,25 @@
// EmulationStation Desktop Edition // EmulationStation Desktop Edition
// Renderer.h // Renderer.h
// //
// General rendering functions. // Generic rendering functions.
// //
#ifndef ES_CORE_RENDERER_RENDERER_H #ifndef ES_CORE_RENDERER_RENDERER_H
#define ES_CORE_RENDERER_RENDERER_H #define ES_CORE_RENDERER_RENDERER_H
#include "Log.h" #include "Log.h"
#include "Shader_GL21.h"
#include "utils/MathUtil.h" #include "utils/MathUtil.h"
#include <stack>
#include <string> #include <string>
#include <vector> #include <vector>
struct SDL_Window; struct SDL_Window;
class Shader;
namespace Renderer class Renderer
{ {
// clang-format off public:
const unsigned int SHADER_CORE {0x00000001};
const unsigned int SHADER_BLUR_HORIZONTAL {0x00000002};
const unsigned int SHADER_BLUR_VERTICAL {0x00000004};
const unsigned int SHADER_SCANLINES {0x00000008};
// clang-format on
struct postProcessingParams {
float opacity;
float saturation;
float dimming;
bool convertBGRAToRGBA;
unsigned int blurPasses;
unsigned int shaders;
postProcessingParams()
: opacity {1.0f}
, saturation {1.0f}
, dimming {1.0f}
, convertBGRAToRGBA {false}
, blurPasses {1}
, shaders {0}
{
}
};
static std::vector<Shader*> sShaderProgramVector;
static GLuint shaderFBO1 {0};
static GLuint shaderFBO2 {0};
static GLuint vertexBuffer1 {0};
static GLuint vertexBuffer2 {0};
// This is simply to get rid of some GCC false positive -Wunused-variable compiler warnings.
static GLuint shaderFBODummy1 {shaderFBO1};
static GLuint shaderFBODummy2 {shaderFBO2};
static GLuint vertexBufferDummy1 {vertexBuffer1};
static GLuint vertexBufferDummy2 {vertexBuffer2};
static constexpr glm::mat4 getIdentity() { return glm::mat4 {1.0f}; }
static inline glm::mat4 mTrans {getIdentity()};
#if !defined(NDEBUG)
#define GL_CHECK_ERROR(Function) (Function, _GLCheckError(#Function))
static inline void _GLCheckError(const std::string& _funcName)
{
const GLenum errorCode = glGetError();
if (errorCode != GL_NO_ERROR) {
#if defined(USE_OPENGLES)
LOG(LogError) << "OpenGL ES error: " << _funcName << " failed with error code: 0x"
<< std::hex << errorCode;
#else
LOG(LogError) << "OpenGL error: " << _funcName << " failed with error code: 0x"
<< std::hex << errorCode;
#endif
}
}
#else
#define GL_CHECK_ERROR(Function) (Function)
#endif
namespace Blend
{
enum Factor {
ZERO,
ONE,
SRC_COLOR,
ONE_MINUS_SRC_COLOR,
SRC_ALPHA,
ONE_MINUS_SRC_ALPHA,
DST_COLOR,
ONE_MINUS_DST_COLOR,
DST_ALPHA,
ONE_MINUS_DST_ALPHA
};
}
namespace Texture
{
enum Type {
RGBA, // Replace with AllowShortEnumsOnASingleLine: false (clang-format >=11.0).
BGRA,
RED
};
}
struct Rect {
Rect(const int xValue, const int yValue, const int wValue, const int hValue)
: x(xValue)
, y(yValue)
, w(wValue)
, h(hValue)
{
}
int x;
int y;
int w;
int h;
};
struct Vertex { struct Vertex {
glm::vec2 position; glm::vec2 position;
glm::vec2 texture; glm::vec2 texture;
@ -142,6 +44,7 @@ namespace Renderer
, shaders {0} , shaders {0}
{ {
} }
Vertex(const glm::vec2& position, const glm::vec2& textureCoord, const unsigned int color) Vertex(const glm::vec2& position, const glm::vec2& textureCoord, const unsigned int color)
: position(position) : position(position)
, texture(textureCoord) , texture(textureCoord)
@ -157,10 +60,71 @@ namespace Renderer
} }
}; };
enum class BlendFactor {
ZERO,
ONE,
SRC_COLOR,
ONE_MINUS_SRC_COLOR,
SRC_ALPHA,
ONE_MINUS_SRC_ALPHA,
DST_COLOR,
ONE_MINUS_DST_COLOR,
DST_ALPHA,
ONE_MINUS_DST_ALPHA
};
enum class TextureType {
RGBA, // Replace with AllowShortEnumsOnASingleLine: false (clang-format >=11.0).
BGRA,
RED
};
struct postProcessingParams {
float opacity;
float saturation;
float dimming;
bool convertBGRAToRGBA;
unsigned int blurPasses;
unsigned int shaders;
postProcessingParams()
: opacity {1.0f}
, saturation {1.0f}
, dimming {1.0f}
, convertBGRAToRGBA {false}
, blurPasses {1}
, shaders {0}
{
}
};
struct Rect {
Rect(const int xValue, const int yValue, const int wValue, const int hValue)
: x(xValue)
, y(yValue)
, w(wValue)
, h(hValue)
{
}
int x;
int y;
int w;
int h;
};
static Renderer* getInstance();
void setIcon();
bool createWindow();
void destroyWindow();
bool init(); bool init();
void deinit(); void deinit();
virtual bool loadShaders() = 0;
void pushClipRect(const glm::ivec2& pos, const glm::ivec2& size); void pushClipRect(const glm::ivec2& pos, const glm::ivec2& size);
void popClipRect(); void popClipRect();
void drawRect(const float x, void drawRect(const float x,
const float y, const float y,
const float w, const float w,
@ -170,56 +134,87 @@ namespace Renderer
bool horizontalGradient = false, bool horizontalGradient = false,
const float opacity = 1.0, const float opacity = 1.0,
const float dimming = 1.0, const float dimming = 1.0,
const Blend::Factor srcBlendFactor = Blend::SRC_ALPHA, const BlendFactor srcBlendFactor = BlendFactor::SRC_ALPHA,
const Blend::Factor dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA); const BlendFactor dstBlendFactor = BlendFactor::ONE_MINUS_SRC_ALPHA);
SDL_Window* getSDLWindow();
const float getWindowWidth();
const float getWindowHeight();
const float getScreenWidth();
const float getScreenHeight();
const float getScreenOffsetX();
const float getScreenOffsetY();
const bool getScreenRotated();
const float getScreenWidthModifier();
const float getScreenHeightModifier();
const float getScreenAspectRatio();
Shader* getShaderProgram(unsigned int shaderID); const glm::mat4& getProjectionMatrix()
const glm::mat4& getProjectionMatrix(); {
const glm::mat4& getProjectionMatrixNormal(); if (mScreenRotated)
void shaderPostprocessing( return mProjectionMatrixRotated;
else
return mProjectionMatrix;
}
const glm::mat4& getProjectionMatrixNormal() { return mProjectionMatrix; }
SDL_Window* getSDLWindow() { return mSDLWindow; }
const bool getScreenRotated() { return mScreenRotated; }
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); }
static const float getScreenHeight() { return static_cast<float>(sScreenHeight); }
static const float getScreenWidthModifier() { return sScreenWidthModifier; }
static const float getScreenHeightModifier() { return sScreenHeightModifier; }
static const float getScreenAspectRatio() { return sScreenAspectRatio; }
static constexpr glm::mat4 getIdentity() { return glm::mat4 {1.0f}; }
glm::mat4 mTrans {getIdentity()};
virtual void shaderPostprocessing(
const unsigned int shaders, const unsigned int shaders,
const Renderer::postProcessingParams& parameters = postProcessingParams(), const Renderer::postProcessingParams& parameters = postProcessingParams(),
unsigned char* textureRGBA = nullptr); unsigned char* textureRGBA = nullptr) = 0;
void setupWindow(); virtual void setup() = 0;
bool createContext(); virtual bool createContext() = 0;
void destroyContext(); virtual void destroyContext() = 0;
unsigned int createTexture(const Texture::Type type, virtual unsigned int createTexture(const TextureType type,
const bool linearMinify, const bool linearMinify,
const bool linearMagnify, const bool linearMagnify,
const bool repeat, const bool repeat,
const unsigned int width,
const unsigned int height,
void* data) = 0;
virtual void destroyTexture(const unsigned int texture) = 0;
virtual void updateTexture(const unsigned int texture,
const TextureType type,
const unsigned int x,
const unsigned int y,
const unsigned int width, const unsigned int width,
const unsigned int height, const unsigned int height,
void* data); void* data) = 0;
void destroyTexture(const unsigned int texture); virtual void bindTexture(const unsigned int texture) = 0;
void updateTexture(const unsigned int texture, virtual void drawTriangleStrips(
const Texture::Type type, const Vertex* vertices,
const unsigned int x, const unsigned int numVertices,
const unsigned int y, const BlendFactor srcBlendFactor = BlendFactor::SRC_ALPHA,
const unsigned int width, const BlendFactor dstBlendFactor = BlendFactor::ONE_MINUS_SRC_ALPHA) = 0;
const unsigned int height, virtual void setMatrix(const glm::mat4& matrix) = 0;
void* data); virtual void setScissor(const Rect& scissor) = 0;
void bindTexture(const unsigned int texture); virtual void setSwapInterval() = 0;
void drawTriangleStrips(const Vertex* vertices, virtual void swapBuffers() = 0;
const unsigned int numVertices,
const Blend::Factor srcBlendFactor = Blend::SRC_ALPHA,
const Blend::Factor dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA);
void setMatrix(const glm::mat4& matrix);
void setScissor(const Rect& scissor);
void setSwapInterval();
void swapBuffers();
} // namespace Renderer // clang-format off
static constexpr unsigned int SHADER_CORE {0x00000001};
static constexpr unsigned int SHADER_BLUR_HORIZONTAL {0x00000002};
static constexpr unsigned int SHADER_BLUR_VERTICAL {0x00000004};
static constexpr unsigned int SHADER_SCANLINES {0x00000008};
// clang-format on
std::stack<Rect> mClipStack;
SDL_Window* mSDLWindow {nullptr};
glm::mat4 mProjectionMatrix {};
glm::mat4 mProjectionMatrixRotated {};
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};
// 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};
};
#endif // ES_CORE_RENDERER_RENDERER_H #endif // ES_CORE_RENDERER_RENDERER_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,92 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// Renderer_GL21.h
//
// OpenGL / OpenGL ES renderering functions.
//
#ifndef ES_CORE_RENDERER_RENDERER_GL21_H
#define ES_CORE_RENDERER_RENDERER_GL21_H
#include "Shader_GL21.h"
#include "renderers/Renderer.h"
#if defined(USE_OPENGLES)
#include <GLES3/gl3.h>
#include <SDL2/SDL_opengles.h>
#else
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#endif
class RendererOpenGL : public Renderer
{
public:
RendererOpenGL() noexcept;
~RendererOpenGL();
static RendererOpenGL* getInstance();
Shader* getShaderProgram(unsigned int shaderID);
bool loadShaders() override;
GLenum convertBlendFactor(const BlendFactor BlendFactorFactor);
GLenum convertTextureType(const TextureType type);
void setup() override;
bool createContext() override;
void destroyContext() override;
void setMatrix(const glm::mat4& matrix) override;
void setScissor(const Rect& scissor) override;
void setSwapInterval() override;
void swapBuffers() override;
unsigned int createTexture(const TextureType type,
const bool linearMinify,
const bool linearMagnify,
const bool repeat,
const unsigned int width,
const unsigned int height,
void* data) override;
void destroyTexture(const unsigned int texture) override;
void updateTexture(const unsigned int texture,
const TextureType type,
const unsigned int x,
const unsigned int y,
const unsigned int width,
const unsigned int height,
void* data) override;
void bindTexture(const unsigned int texture) override;
void drawTriangleStrips(
const Vertex* vertices,
const unsigned int numVertices,
const BlendFactor srcBlendFactor = BlendFactor::SRC_ALPHA,
const BlendFactor dstBlendFactor = BlendFactor::ONE_MINUS_SRC_ALPHA) override;
void shaderPostprocessing(
const unsigned int shaders,
const Renderer::postProcessingParams& parameters = postProcessingParams(),
unsigned char* textureRGBA = nullptr) override;
private:
std::vector<Shader*> mShaderProgramVector;
GLuint mShaderFBO1;
GLuint mShaderFBO2;
GLuint mVertexBuffer1;
GLuint mVertexBuffer2;
SDL_GLContext mSDLContext;
GLuint mWhiteTexture;
GLuint mPostProcTexture1;
GLuint mPostProcTexture2;
Shader* mCoreShader;
Shader* mBlurHorizontalShader;
Shader* mBlurVerticalShader;
Shader* mScanlinelShader;
Shader* mLastShader;
};
#endif // ES_CORE_RENDERER_RENDERER_GL21_H

View file

@ -12,254 +12,246 @@
#include "renderers/Renderer.h" #include "renderers/Renderer.h"
#include "resources/ResourceManager.h" #include "resources/ResourceManager.h"
namespace Renderer Shader::Shader()
: mProgramID {0}
, mShaderMVPMatrix {0}
, mShaderPosition {0}
, mShaderTextureCoord {0}
, mShaderColor {0}
, mShaderTextureSize {0}
, mShaderOpacity {0}
, mShaderSaturation {0}
, mShaderDimming {0}
, mShaderBGRAToRGBA {0}
, mShaderFont {0}
, mShaderPostProcessing {0}
{ {
Renderer::Shader::Shader() }
: mProgramID {0}
, shaderMVPMatrix {0}
, shaderPosition {0}
, shaderTextureCoord {0}
, shaderColor {0}
, shaderTextureSize {0}
, shaderOpacity {0}
, shaderSaturation {0}
, shaderDimming {0}
, shaderBGRAToRGBA {0}
, shaderFont {0}
, shaderPostProcessing {0}
{
}
Renderer::Shader::~Shader() Shader::~Shader()
{ {
// Delete the shader program when destroyed. // Delete the shader program when destroyed.
deleteProgram(mProgramID); deleteProgram(mProgramID);
} }
void Renderer::Shader::loadShaderFile(const std::string& path, GLenum shaderType) void Shader::loadShaderFile(const std::string& path, GLenum shaderType)
{ {
std::string preprocessorDefines; std::string preprocessorDefines;
std::string shaderCode; std::string shaderCode;
// This will load the entire GLSL source code into the string variable. // This will load the entire GLSL source code into the string variable.
const ResourceData& shaderData {ResourceManager::getInstance().getFileData(path)}; const ResourceData& shaderData {ResourceManager::getInstance().getFileData(path)};
shaderCode.assign(reinterpret_cast<const char*>(shaderData.ptr.get()), shaderData.length); shaderCode.assign(reinterpret_cast<const char*>(shaderData.ptr.get()), shaderData.length);
// Define the GLSL version. // Define the GLSL version.
#if defined(USE_OPENGLES) #if defined(USE_OPENGLES)
preprocessorDefines = "#version 300 es\n"; preprocessorDefines = "#version 300 es\n";
#else #else
preprocessorDefines = "#version 330\n"; preprocessorDefines = "#version 330\n";
#endif #endif
// Define the preprocessor constants that will let the shader compiler know whether // Define the preprocessor constants that will let the shader compiler know whether
// the VERTEX or FRAGMENT portion of the code should be used. // the VERTEX or FRAGMENT portion of the code should be used.
if (shaderType == GL_VERTEX_SHADER) if (shaderType == GL_VERTEX_SHADER)
preprocessorDefines += "#define VERTEX\n"; preprocessorDefines += "#define VERTEX\n";
else if (shaderType == GL_FRAGMENT_SHADER) else if (shaderType == GL_FRAGMENT_SHADER)
preprocessorDefines += "#define FRAGMENT\n"; preprocessorDefines += "#define FRAGMENT\n";
shaderVector.push_back(std::make_tuple(path, preprocessorDefines + shaderCode, shaderType)); mShaderVector.push_back(std::make_tuple(path, preprocessorDefines + shaderCode, shaderType));
} }
bool Renderer::Shader::createProgram() bool Shader::createProgram()
{ {
GLint programSuccess; GLint programSuccess;
mProgramID = glCreateProgram(); mProgramID = glCreateProgram();
// Compile and attach all shaders that have been loaded. // Compile and attach all shaders that have been loaded.
for (auto it = shaderVector.cbegin(); it != shaderVector.cend(); ++it) { for (auto it = mShaderVector.cbegin(); it != mShaderVector.cend(); ++it) {
GLuint currentShader = glCreateShader(std::get<2>(*it)); GLuint currentShader {glCreateShader(std::get<2>(*it))};
GLchar const* shaderCodePtr = std::get<1>(*it).c_str(); GLchar const* shaderCodePtr {std::get<1>(*it).c_str()};
glShaderSource(currentShader, 1, reinterpret_cast<const GLchar**>(&shaderCodePtr), glShaderSource(currentShader, 1, reinterpret_cast<const GLchar**>(&shaderCodePtr), nullptr);
nullptr); glCompileShader(currentShader);
glCompileShader(currentShader);
GLint shaderCompiled; GLint shaderCompiled;
glGetShaderiv(currentShader, GL_COMPILE_STATUS, &shaderCompiled); glGetShaderiv(currentShader, GL_COMPILE_STATUS, &shaderCompiled);
if (shaderCompiled != GL_TRUE) { if (shaderCompiled != GL_TRUE) {
LOG(LogError) << "OpenGL error: Unable to compile shader " << currentShader << " (" LOG(LogError) << "OpenGL error: Unable to compile shader " << currentShader << " ("
<< std::get<0>(*it) << ")."; << std::get<0>(*it) << ").";
printShaderInfoLog(currentShader, std::get<2>(*it), true); printShaderInfoLog(currentShader, std::get<2>(*it), true);
return false;
}
else {
printShaderInfoLog(currentShader, std::get<2>(*it), false);
}
GL_CHECK_ERROR(glAttachShader(mProgramID, currentShader));
}
glLinkProgram(mProgramID);
glGetProgramiv(mProgramID, GL_LINK_STATUS, &programSuccess);
if (programSuccess != GL_TRUE) {
LOG(LogError) << "OpenGL error: Unable to link program " << mProgramID << ".";
printProgramInfoLog(mProgramID);
return false; return false;
} }
getVariableLocations(mProgramID);
if (shaderPosition != -1)
GL_CHECK_ERROR(glEnableVertexAttribArray(shaderPosition));
if (shaderTextureCoord != -1)
GL_CHECK_ERROR(glEnableVertexAttribArray(shaderTextureCoord));
if (shaderColor != -1)
GL_CHECK_ERROR(glEnableVertexAttribArray(shaderColor));
return true;
}
void Renderer::Shader::deleteProgram(GLuint programID)
{
GL_CHECK_ERROR(glDeleteProgram(programID));
}
void Renderer::Shader::getVariableLocations(GLuint programID)
{
// Some of the variable names are chosen to be compatible with the RetroArch GLSL shaders.
shaderMVPMatrix = glGetUniformLocation(mProgramID, "MVPMatrix");
shaderPosition = glGetAttribLocation(mProgramID, "positionAttrib");
shaderTextureCoord = glGetAttribLocation(mProgramID, "TexCoord");
shaderColor = glGetAttribLocation(mProgramID, "colorAttrib");
shaderTextureSize = glGetUniformLocation(mProgramID, "TextureSize");
shaderOpacity = glGetUniformLocation(mProgramID, "opacity");
shaderSaturation = glGetUniformLocation(mProgramID, "saturation");
shaderDimming = glGetUniformLocation(mProgramID, "dimming");
shaderBGRAToRGBA = glGetUniformLocation(mProgramID, "BGRAToRGBA");
shaderFont = glGetUniformLocation(mProgramID, "font");
shaderPostProcessing = glGetUniformLocation(mProgramID, "postProcessing");
}
void Renderer::Shader::setModelViewProjectionMatrix(glm::mat4 mvpMatrix)
{
if (shaderMVPMatrix != GL_INVALID_VALUE && shaderMVPMatrix != GL_INVALID_OPERATION)
GL_CHECK_ERROR(glUniformMatrix4fv(shaderMVPMatrix, 1, GL_FALSE,
reinterpret_cast<GLfloat*>(&mvpMatrix)));
}
void Renderer::Shader::setAttribPointers()
{
if (shaderPosition != -1)
GL_CHECK_ERROR(
glVertexAttribPointer(shaderPosition, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<const void*>(offsetof(Vertex, position))));
if (shaderTextureCoord != -1)
GL_CHECK_ERROR(
glVertexAttribPointer(shaderTextureCoord, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<const void*>(offsetof(Vertex, texture))));
if (shaderColor != -1)
GL_CHECK_ERROR(
glVertexAttribPointer(shaderColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex),
reinterpret_cast<const void*>(offsetof(Vertex, color))));
}
void Renderer::Shader::setTextureSize(std::array<GLfloat, 2> shaderVec2)
{
if (shaderTextureSize != -1)
GL_CHECK_ERROR(glUniform2f(shaderTextureSize, shaderVec2[0], shaderVec2[1]));
}
void Renderer::Shader::setOpacity(GLfloat opacity)
{
if (shaderOpacity != -1)
GL_CHECK_ERROR(glUniform1f(shaderOpacity, opacity));
}
void Renderer::Shader::setSaturation(GLfloat saturation)
{
if (shaderSaturation != -1)
GL_CHECK_ERROR(glUniform1f(shaderSaturation, saturation));
}
void Renderer::Shader::setDimming(GLfloat dimming)
{
if (shaderDimming != -1)
GL_CHECK_ERROR(glUniform1f(shaderDimming, dimming));
}
void Renderer::Shader::setBGRAToRGBA(GLboolean BGRAToRGBA)
{
if (shaderBGRAToRGBA != -1)
GL_CHECK_ERROR(glUniform1i(shaderBGRAToRGBA, BGRAToRGBA ? 1 : 0));
}
void Renderer::Shader::setFont(GLboolean font)
{
if (shaderFont != -1)
GL_CHECK_ERROR(glUniform1i(shaderFont, font ? 1 : 0));
}
void Renderer::Shader::setPostProcessing(GLboolean postProcessing)
{
if (shaderPostProcessing != -1)
GL_CHECK_ERROR(glUniform1i(shaderPostProcessing, postProcessing ? 1 : 0));
}
void Renderer::Shader::activateShaders()
{
// Install the shader program.
GL_CHECK_ERROR(glUseProgram(mProgramID));
}
void Renderer::Shader::deactivateShaders()
{
// Remove the shader program.
GL_CHECK_ERROR(glUseProgram(0));
}
void Renderer::Shader::printProgramInfoLog(GLuint programID)
{
if (glIsProgram(programID)) {
int logLength;
int maxLength;
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<char> infoLog(maxLength);
glGetProgramInfoLog(programID, maxLength, &logLength, &infoLog.front());
if (logLength > 0) {
LOG(LogDebug) << "Renderer_GL21::printProgramInfoLog():\n"
<< std::string(infoLog.begin(), infoLog.end());
}
}
else { else {
LOG(LogError) << "OpenGL error: " << programID << " is not a program."; printShaderInfoLog(currentShader, std::get<2>(*it), false);
} }
GL_CHECK_ERROR(glAttachShader(mProgramID, currentShader));
} }
void Renderer::Shader::printShaderInfoLog(GLuint shaderID, GLenum shaderType, bool error) glLinkProgram(mProgramID);
{
if (glIsShader(shaderID)) {
int logLength;
int maxLength;
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &maxLength); glGetProgramiv(mProgramID, GL_LINK_STATUS, &programSuccess);
std::vector<char> infoLog(maxLength); if (programSuccess != GL_TRUE) {
LOG(LogError) << "OpenGL error: Unable to link program " << mProgramID << ".";
if (infoLog.size() == 0) printProgramInfoLog(mProgramID);
return; return false;
glGetShaderInfoLog(shaderID, maxLength, &logLength, &infoLog.front());
if (logLength > 0) {
LOG(LogDebug) << "Shader_GL21::printShaderInfoLog(): "
<< (error ? "Error" : "Warning") << " in "
<< (shaderType == GL_VERTEX_SHADER ? "VERTEX section:\n" :
"FRAGMENT section:\n")
<< std::string(infoLog.begin(), infoLog.end());
}
}
else {
LOG(LogError) << "OpenGL error: " << shaderID << " is not a shader.";
}
} }
} // namespace Renderer getVariableLocations(mProgramID);
if (mShaderPosition != -1)
GL_CHECK_ERROR(glEnableVertexAttribArray(mShaderPosition));
if (mShaderTextureCoord != -1)
GL_CHECK_ERROR(glEnableVertexAttribArray(mShaderTextureCoord));
if (mShaderColor != -1)
GL_CHECK_ERROR(glEnableVertexAttribArray(mShaderColor));
return true;
}
void Shader::deleteProgram(GLuint programID) { GL_CHECK_ERROR(glDeleteProgram(programID)); }
void Shader::getVariableLocations(GLuint programID)
{
// Some of the variable names are chosen to be compatible with the RetroArch GLSL shaders.
mShaderMVPMatrix = glGetUniformLocation(mProgramID, "MVPMatrix");
mShaderPosition = glGetAttribLocation(mProgramID, "positionAttrib");
mShaderTextureCoord = glGetAttribLocation(mProgramID, "TexCoord");
mShaderColor = glGetAttribLocation(mProgramID, "colorAttrib");
mShaderTextureSize = glGetUniformLocation(mProgramID, "TextureSize");
mShaderOpacity = glGetUniformLocation(mProgramID, "opacity");
mShaderSaturation = glGetUniformLocation(mProgramID, "saturation");
mShaderDimming = glGetUniformLocation(mProgramID, "dimming");
mShaderBGRAToRGBA = glGetUniformLocation(mProgramID, "BGRAToRGBA");
mShaderFont = glGetUniformLocation(mProgramID, "font");
mShaderPostProcessing = glGetUniformLocation(mProgramID, "postProcessing");
}
void Shader::setModelViewProjectionMatrix(glm::mat4 mvpMatrix)
{
if (mShaderMVPMatrix != GL_INVALID_VALUE && mShaderMVPMatrix != GL_INVALID_OPERATION)
GL_CHECK_ERROR(glUniformMatrix4fv(mShaderMVPMatrix, 1, GL_FALSE,
reinterpret_cast<GLfloat*>(&mvpMatrix)));
}
void Shader::setAttribPointers()
{
if (mShaderPosition != -1)
GL_CHECK_ERROR(glVertexAttribPointer(
mShaderPosition, 2, GL_FLOAT, GL_FALSE, sizeof(Renderer::Vertex),
reinterpret_cast<const void*>(offsetof(Renderer::Vertex, position))));
if (mShaderTextureCoord != -1)
GL_CHECK_ERROR(glVertexAttribPointer(
mShaderTextureCoord, 2, GL_FLOAT, GL_FALSE, sizeof(Renderer::Vertex),
reinterpret_cast<const void*>(offsetof(Renderer::Vertex, texture))));
if (mShaderColor != -1)
GL_CHECK_ERROR(glVertexAttribPointer(
mShaderColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Renderer::Vertex),
reinterpret_cast<const void*>(offsetof(Renderer::Vertex, color))));
}
void Shader::setTextureSize(std::array<GLfloat, 2> shaderVec2)
{
if (mShaderTextureSize != -1)
GL_CHECK_ERROR(glUniform2f(mShaderTextureSize, shaderVec2[0], shaderVec2[1]));
}
void Shader::setOpacity(GLfloat opacity)
{
if (mShaderOpacity != -1)
GL_CHECK_ERROR(glUniform1f(mShaderOpacity, opacity));
}
void Shader::setSaturation(GLfloat saturation)
{
if (mShaderSaturation != -1)
GL_CHECK_ERROR(glUniform1f(mShaderSaturation, saturation));
}
void Shader::setDimming(GLfloat dimming)
{
if (mShaderDimming != -1)
GL_CHECK_ERROR(glUniform1f(mShaderDimming, dimming));
}
void Shader::setBGRAToRGBA(GLboolean BGRAToRGBA)
{
if (mShaderBGRAToRGBA != -1)
GL_CHECK_ERROR(glUniform1i(mShaderBGRAToRGBA, BGRAToRGBA ? 1 : 0));
}
void Shader::setFont(GLboolean font)
{
if (mShaderFont != -1)
GL_CHECK_ERROR(glUniform1i(mShaderFont, font ? 1 : 0));
}
void Shader::setPostProcessing(GLboolean postProcessing)
{
if (mShaderPostProcessing != -1)
GL_CHECK_ERROR(glUniform1i(mShaderPostProcessing, postProcessing ? 1 : 0));
}
void Shader::activateShaders()
{
// Install the shader program.
GL_CHECK_ERROR(glUseProgram(mProgramID));
}
void Shader::deactivateShaders()
{
// Remove the shader program.
GL_CHECK_ERROR(glUseProgram(0));
}
void Shader::printProgramInfoLog(GLuint programID)
{
if (glIsProgram(programID)) {
int logLength;
int maxLength;
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<char> infoLog(maxLength);
glGetProgramInfoLog(programID, maxLength, &logLength, &infoLog.front());
if (logLength > 0) {
LOG(LogDebug) << "Renderer_GL21::printProgramInfoLog():\n"
<< std::string(infoLog.begin(), infoLog.end());
}
}
else {
LOG(LogError) << "OpenGL error: " << programID << " is not a program.";
}
}
void Shader::printShaderInfoLog(GLuint shaderID, GLenum shaderType, bool error)
{
if (glIsShader(shaderID)) {
int logLength;
int maxLength;
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<char> infoLog(maxLength);
if (infoLog.size() == 0)
return;
glGetShaderInfoLog(shaderID, maxLength, &logLength, &infoLog.front());
if (logLength > 0) {
LOG(LogDebug) << "Shader_GL21::printShaderInfoLog(): " << (error ? "Error" : "Warning")
<< " in "
<< (shaderType == GL_VERTEX_SHADER ? "VERTEX section:\n" :
"FRAGMENT section:\n")
<< std::string(infoLog.begin(), infoLog.end());
}
}
else {
LOG(LogError) << "OpenGL error: " << shaderID << " is not a shader.";
}
}

View file

@ -11,6 +11,7 @@
#define GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES
#include "renderers/Renderer.h"
#include "utils/MathUtil.h" #include "utils/MathUtil.h"
#if defined(_WIN64) #if defined(_WIN64)
@ -28,61 +29,77 @@
#include <string> #include <string>
#include <vector> #include <vector>
namespace Renderer #if !defined(NDEBUG)
#define GL_CHECK_ERROR(Function) (Function, _GLCheckError(#Function))
static inline void _GLCheckError(const std::string& funcName)
{ {
class Shader const GLenum errorCode = glGetError();
{
public:
Shader();
~Shader();
// Loads the shader source code only, no compilation done at this point. if (errorCode != GL_NO_ERROR) {
void loadShaderFile(const std::string& path, GLenum shaderType); #if defined(USE_OPENGLES)
// Compilation, shader attachment and linking. LOG(LogError) << "OpenGL ES error: " << funcName << " failed with error code: 0x"
bool createProgram(); << std::hex << errorCode;
// Only used for a clean shutdown. #else
void deleteProgram(GLuint programID); LOG(LogError) << "OpenGL error: " << funcName << " failed with error code: 0x" << std::hex
// Get references to the variables inside the compiled shaders. << errorCode;
void getVariableLocations(GLuint programID); #endif
// One-way communication with the compiled shaders. }
void setModelViewProjectionMatrix(glm::mat4 mvpMatrix); }
#else
#define GL_CHECK_ERROR(Function) (Function)
#endif
void setAttribPointers(); class Shader
void setTextureSize(std::array<GLfloat, 2> shaderVec2); {
void setOpacity(GLfloat opacity); public:
void setSaturation(GLfloat saturation); Shader();
void setDimming(GLfloat dimming); ~Shader();
void setBGRAToRGBA(GLboolean BGRAToRGBA);
void setFont(GLboolean font);
void setPostProcessing(GLboolean postProcessing);
// Sets the shader program to use the loaded shaders.
void activateShaders();
// Sets the shader program to 0 which reverts to the fixed function pipeline.
void deactivateShaders();
// Returns the program ID that was generated by glCreateProgram().
GLuint getProgramID() { return mProgramID; }
// Only used for error logging if the shaders fail to compile or link.
void printProgramInfoLog(GLuint programID);
void printShaderInfoLog(GLuint shaderID, GLenum shaderType, bool error);
private: // Loads the shader source code only, no compilation done at this point.
GLuint mProgramID; void loadShaderFile(const std::string& path, GLenum shaderType);
std::vector<std::tuple<std::string, std::string, GLenum>> shaderVector; // Compilation, shader attachment and linking.
bool createProgram();
// Only used for a clean shutdown.
void deleteProgram(GLuint programID);
// Get references to the variables inside the compiled shaders.
void getVariableLocations(GLuint programID);
// One-way communication with the compiled shaders.
void setModelViewProjectionMatrix(glm::mat4 mvpMatrix);
// Variables used for communication with the compiled shaders. void setAttribPointers();
GLint shaderMVPMatrix; void setTextureSize(std::array<GLfloat, 2> shaderVec2);
GLint shaderPosition; void setOpacity(GLfloat opacity);
GLint shaderTextureCoord; void setSaturation(GLfloat saturation);
GLint shaderColor; void setDimming(GLfloat dimming);
GLint shaderTextureSize; void setBGRAToRGBA(GLboolean BGRAToRGBA);
GLint shaderOpacity; void setFont(GLboolean font);
GLint shaderSaturation; void setPostProcessing(GLboolean postProcessing);
GLint shaderDimming; // Sets the shader program to use the loaded shaders.
GLint shaderBGRAToRGBA; void activateShaders();
GLint shaderFont; // Sets the shader program to 0 which reverts to the fixed function pipeline.
GLint shaderPostProcessing; void deactivateShaders();
}; // Returns the program ID that was generated by glCreateProgram().
GLuint getProgramID() { return mProgramID; }
// Only used for error logging if the shaders fail to compile or link.
void printProgramInfoLog(GLuint programID);
void printShaderInfoLog(GLuint shaderID, GLenum shaderType, bool error);
} // namespace Renderer private:
GLuint mProgramID;
std::vector<std::tuple<std::string, std::string, GLenum>> mShaderVector;
// Variables used for communication with the compiled shaders.
GLint mShaderMVPMatrix;
GLint mShaderPosition;
GLint mShaderTextureCoord;
GLint mShaderColor;
GLint mShaderTextureSize;
GLint mShaderOpacity;
GLint mShaderSaturation;
GLint mShaderDimming;
GLint mShaderBGRAToRGBA;
GLint mShaderFont;
GLint mShaderPostProcessing;
};
#endif // ES_CORE_RENDERER_SHADER_GL21_H #endif // ES_CORE_RENDERER_SHADER_GL21_H

View file

@ -76,7 +76,8 @@ size_t Font::getTotalMemUsage()
} }
Font::Font(int size, const std::string& path) Font::Font(int size, const std::string& path)
: mSize(size) : mRenderer {Renderer::getInstance()}
, mSize(size)
, mPath(path) , mPath(path)
{ {
if (mSize < 9) { if (mSize < 9) {
@ -199,14 +200,14 @@ bool Font::FontTexture::findEmpty(const glm::ivec2& size, glm::ivec2& cursor_out
void Font::FontTexture::initTexture() void Font::FontTexture::initTexture()
{ {
assert(textureId == 0); assert(textureId == 0);
textureId = Renderer::createTexture(Renderer::Texture::RED, false, false, false, textureSize.x, textureId = Renderer::getInstance()->createTexture(
textureSize.y, nullptr); Renderer::TextureType::RED, false, false, false, textureSize.x, textureSize.y, nullptr);
} }
void Font::FontTexture::deinitTexture() void Font::FontTexture::deinitTexture()
{ {
if (textureId != 0) { if (textureId != 0) {
Renderer::destroyTexture(textureId); Renderer::getInstance()->destroyTexture(textureId);
textureId = 0; textureId = 0;
} }
} }
@ -346,8 +347,8 @@ Font::Glyph* Font::getGlyph(unsigned int id)
static_cast<float>(g->metrics.horiBearingY) / 64.0f}; static_cast<float>(g->metrics.horiBearingY) / 64.0f};
// Upload glyph bitmap to texture. // Upload glyph bitmap to texture.
Renderer::updateTexture(tex->textureId, Renderer::Texture::RED, cursor.x, cursor.y, glyphSize.x, mRenderer->updateTexture(tex->textureId, Renderer::TextureType::RED, cursor.x, cursor.y,
glyphSize.y, g->bitmap.buffer); glyphSize.x, glyphSize.y, g->bitmap.buffer);
// Update max glyph height. // Update max glyph height.
if (glyphSize.y > mMaxGlyphHeight) if (glyphSize.y > mMaxGlyphHeight)
@ -380,8 +381,8 @@ void Font::rebuildTextures()
static_cast<int>(it->second.texSize.y * tex->textureSize.y)}; static_cast<int>(it->second.texSize.y * tex->textureSize.y)};
// Upload to texture. // Upload to texture.
Renderer::updateTexture(tex->textureId, Renderer::Texture::RED, cursor.x, cursor.y, mRenderer->updateTexture(tex->textureId, Renderer::TextureType::RED, cursor.x, cursor.y,
glyphSize.x, glyphSize.y, glyphSlot->bitmap.buffer); glyphSize.x, glyphSize.y, glyphSlot->bitmap.buffer);
} }
} }
@ -398,9 +399,9 @@ void Font::renderTextCache(TextCache* cache)
auto vertexList = *it; auto vertexList = *it;
it->verts[0].font = true; it->verts[0].font = true;
Renderer::bindTexture(*it->textureIdPtr); mRenderer->bindTexture(*it->textureIdPtr);
Renderer::drawTriangleStrips(&it->verts[0], mRenderer->drawTriangleStrips(&it->verts[0],
static_cast<const unsigned int>(it->verts.size())); static_cast<const unsigned int>(it->verts.size()));
} }
} }

View file

@ -107,6 +107,7 @@ public:
static size_t getTotalMemUsage(); static size_t getTotalMemUsage();
private: private:
Renderer* mRenderer;
static FT_Library sLibrary; static FT_Library sLibrary;
static std::map<std::pair<std::string, int>, std::weak_ptr<Font>> sFontMap; static std::map<std::pair<std::string, int>, std::weak_ptr<Font>> sFontMap;

View file

@ -24,7 +24,8 @@
#define DPI 96 #define DPI 96
TextureData::TextureData(bool tile) TextureData::TextureData(bool tile)
: mTile {tile} : mRenderer {Renderer::getInstance()}
, mTile {tile}
, mTextureID {0} , mTextureID {0}
, mDataRGBA {} , mDataRGBA {}
, mWidth {0} , mWidth {0}
@ -209,7 +210,7 @@ bool TextureData::uploadAndBind()
// Check if it has already been uploaded. // Check if it has already been uploaded.
std::unique_lock<std::mutex> lock(mMutex); std::unique_lock<std::mutex> lock(mMutex);
if (mTextureID != 0) { if (mTextureID != 0) {
Renderer::bindTexture(mTextureID); mRenderer->bindTexture(mTextureID);
} }
else { else {
// Make sure we're ready to upload. // Make sure we're ready to upload.
@ -218,9 +219,9 @@ bool TextureData::uploadAndBind()
// Upload texture. // Upload texture.
mTextureID = mTextureID =
Renderer::createTexture(Renderer::Texture::RGBA, true, mLinearMagnify, mTile, mRenderer->createTexture(Renderer::TextureType::RGBA, true, mLinearMagnify, mTile,
static_cast<const unsigned int>(mWidth), static_cast<const unsigned int>(mWidth),
static_cast<const unsigned int>(mHeight), mDataRGBA.data()); static_cast<const unsigned int>(mHeight), mDataRGBA.data());
} }
return true; return true;
} }
@ -229,7 +230,7 @@ void TextureData::releaseVRAM()
{ {
std::unique_lock<std::mutex> lock(mMutex); std::unique_lock<std::mutex> lock(mMutex);
if (mTextureID != 0) { if (mTextureID != 0) {
Renderer::destroyTexture(mTextureID); mRenderer->destroyTexture(mTextureID);
mTextureID = 0; mTextureID = 0;
} }
} }

View file

@ -72,6 +72,7 @@ public:
bool tiled() { return mTile; } bool tiled() { return mTile; }
private: private:
Renderer* mRenderer;
std::mutex mMutex; std::mutex mMutex;
bool mTile; bool mTile;