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
// from the game.
if (!runInBackground)
Renderer::swapBuffers();
Renderer::getInstance()->swapBuffers();
Scripting::fireEvent("game-start", romPath, getSourceFileData()->metadata.get("name"),
getSourceFileData()->getSystem()->getName(),

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -38,7 +38,8 @@
#define FAILED_VERIFICATION_RETRIES 8
GuiScraperSearch::GuiScraperSearch(SearchType type, unsigned int scrapeCount)
: mGrid {glm::ivec2 {5, 3}}
: mRenderer {Renderer::getInstance()}
, mGrid {glm::ivec2 {5, 3}}
, mSearchType {type}
, mScrapeCount {scrapeCount}
, mRefinedSearch {false}
@ -630,10 +631,10 @@ void GuiScraperSearch::render(const glm::mat4& parentTrans)
glm::mat4 trans {parentTrans * getTransform()};
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) {
Renderer::setMatrix(trans);
mRenderer->setMatrix(trans);
mBusyAnim.render(trans);
}
}

View file

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

View file

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

View file

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

View file

@ -18,8 +18,9 @@
GamelistView::GamelistView(FileData* root)
: GamelistBase {root}
, mLegacyMode {false}
, mRenderer {Renderer::getInstance()}
, mViewStyle {ViewController::BASIC}
, mLegacyMode {false}
{
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)),
static_cast<int>(std::round(mSize.y * scaleY))};
Renderer::pushClipRect(pos, size);
mRenderer->pushClipRect(pos, size);
renderChildren(trans);
Renderer::popClipRect();
mRenderer->popClipRect();
}
HelpStyle GamelistView::getHelpStyle()

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -74,6 +74,7 @@ set(CORE_HEADERS
# Renderers
${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
# Resources

View file

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

View file

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

View file

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

View file

@ -21,6 +21,7 @@ namespace
CarouselComponent::CarouselComponent()
: IList<CarouselElement, SystemData*> {LIST_SCROLL_STYLE_SLOW, LIST_ALWAYS_LOOP}
, mRenderer {Renderer::getInstance()}
, mCamOffset {0.0f}
, mPreviousScrollVelocity {0}
, 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});
glm::vec2 clipPos {carouselTrans[3].x, carouselTrans[3].y};
Renderer::setMatrix(carouselTrans);
mRenderer->setMatrix(carouselTrans);
// Background box behind logos.
Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, mCarouselColor, mCarouselColorEnd,
mColorGradientHorizontal);
mRenderer->drawRect(0.0f, 0.0f, mSize.x, mSize.y, mCarouselColor, mCarouselColorEnd,
mColorGradientHorizontal);
// Draw logos.
// logoSpacing will also include the size of the logo itself.

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -20,7 +20,8 @@
#include "ThemeData.h"
FlexboxComponent::FlexboxComponent(std::vector<FlexboxItem>& items)
: mItems {items}
: mRenderer {Renderer::getInstance()}
, mItems {items}
, mDirection {DEFAULT_DIRECTION}
, mAlignment {DEFAULT_ALIGNMENT}
, mLines {DEFAULT_LINES}
@ -42,10 +43,10 @@ void FlexboxComponent::render(const glm::mat4& parentTrans)
computeLayout();
glm::mat4 trans {parentTrans * getTransform()};
Renderer::setMatrix(trans);
mRenderer->setMatrix(trans);
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) {
if (!item.visible)

View file

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

View file

@ -20,7 +20,8 @@
#include "utils/StringUtil.h"
GIFAnimComponent::GIFAnimComponent()
: mFrameSize {0}
: mRenderer {Renderer::getInstance()}
, mFrameSize {0}
, mAnimFile {nullptr}
, mAnimation {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"))
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) {
mTexture->bind();
@ -493,6 +494,6 @@ void GIFAnimComponent::render(const glm::mat4& parentTrans)
vertices->convertBGRAToRGBA = true;
// 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));
}
Renderer* mRenderer;
std::shared_ptr<TextureResource> mTexture;
std::vector<uint8_t> mPictureRGBA;
size_t mFrameSize;

View file

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

View file

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

View file

@ -16,7 +16,8 @@
#include "resources/ResourceManager.h"
LottieAnimComponent::LottieAnimComponent()
: mCacheFrames {true}
: mRenderer {Renderer::getInstance()}
, mCacheFrames {true}
, mMaxCacheSize {0}
, mCacheSize {0}
, mFrameSize {0}
@ -53,8 +54,8 @@ LottieAnimComponent::LottieAnimComponent()
// Set component defaults.
setOrigin(0.5f, 0.5f);
setSize(Renderer::getScreenWidth() * 0.2f, Renderer::getScreenHeight() * 0.2f);
setPosition(Renderer::getScreenWidth() * 0.3f, Renderer::getScreenHeight() * 0.3f);
setSize(mRenderer->getScreenWidth() * 0.2f, mRenderer->getScreenHeight() * 0.2f);
setPosition(mRenderer->getScreenWidth() * 0.3f, mRenderer->getScreenHeight() * 0.3f);
setDefaultZIndex(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"))
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) {
mTexture->bind();
@ -482,6 +483,6 @@ void LottieAnimComponent::render(const glm::mat4& parentTrans)
vertices->convertBGRAToRGBA = true;
// Render it.
Renderer::drawTriangleStrips(&vertices[0], 4);
mRenderer->drawTriangleStrips(&vertices[0], 4);
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -15,7 +15,8 @@
#include "resources/Font.h"
ScrollableContainer::ScrollableContainer()
: mScrollPos {0.0f, 0.0f}
: mRenderer {Renderer::getInstance()}
, mScrollPos {0.0f, 0.0f}
, mScrollDir {0.0f, 0.0f}
, mClipSpacing {0.0f}
, mAutoScrollDelay {0}
@ -233,11 +234,11 @@ void ScrollableContainer::render(const glm::mat4& parentTrans)
clipPos.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});
Renderer::setMatrix(trans);
mRenderer->setMatrix(trans);
GuiComponent::renderChildren(trans);
Renderer::popClipRect();
mRenderer->popClipRect();
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -19,7 +19,8 @@
#define BLINKTIME 1000
TextEditComponent::TextEditComponent()
: mFocused {false}
: mRenderer {Renderer::getInstance()}
, mFocused {false}
, mEditing {false}
, mCursor {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),
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});
Renderer::setMatrix(trans);
mRenderer->setMatrix(trans);
if (mTextCache)
mFont->renderTextCache(mTextCache.get());
// Pop the clip early to allow the cursor to be drawn outside of the "text area".
Renderer::popClipRect();
mRenderer->popClipRect();
// Draw cursor.
glm::vec2 cursorPos;
@ -328,15 +329,15 @@ void TextEditComponent::render(const glm::mat4& parentTrans)
float cursorHeight = mFont->getHeight() * 0.8f;
if (!mEditing) {
Renderer::drawRect(cursorPos.x, cursorPos.y + (mFont->getHeight() - cursorHeight) / 2.0f,
2.0f * Renderer::getScreenWidthModifier(), cursorHeight, 0xC7C7C7FF,
0xC7C7C7FF);
mRenderer->drawRect(cursorPos.x, cursorPos.y + (mFont->getHeight() - cursorHeight) / 2.0f,
2.0f * Renderer::getScreenWidthModifier(), cursorHeight, 0xC7C7C7FF,
0xC7C7C7FF);
}
if (mEditing && mBlinkTime < BLINKTIME / 2) {
Renderer::drawRect(cursorPos.x, cursorPos.y + (mFont->getHeight() - cursorHeight) / 2.0f,
2.0f * Renderer::getScreenWidthModifier(), cursorHeight, 0x777777FF,
0x777777FF);
mRenderer->drawRect(cursorPos.x, cursorPos.y + (mFont->getHeight() - cursorHeight) / 2.0f,
2.0f * Renderer::getScreenWidthModifier(), cursorHeight, 0x777777FF,
0x777777FF);
}
}

View file

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

View file

@ -135,6 +135,7 @@ protected:
void onCursorChanged(const CursorState& state) override;
private:
Renderer* mRenderer;
int mLoopOffset;
int mLoopOffset2;
int mLoopTime;
@ -164,6 +165,7 @@ private:
template <typename T> TextListComponent<T>::TextListComponent()
{
mRenderer = Renderer::getInstance();
mLoopOffset = 0;
mLoopOffset2 = 0;
mLoopTime = 0;
@ -232,17 +234,17 @@ template <typename T> void TextListComponent<T>::render(const glm::mat4& parentT
mSelectorImage.render(trans);
}
else {
Renderer::setMatrix(trans);
Renderer::drawRect(0.0f, (mCursor - startEntry) * entrySize + mSelectorOffsetY, mSize.x,
mSelectorHeight, mSelectorColor, mSelectorColorEnd,
mSelectorColorGradientHorizontal);
mRenderer->setMatrix(trans);
mRenderer->drawRect(0.0f, (mCursor - startEntry) * entrySize + mSelectorOffsetY,
mSize.x, mSelectorHeight, mSelectorColor, mSelectorColorEnd,
mSelectorColorGradientHorizontal);
}
}
if (Settings::getInstance()->getBool("DebugText")) {
Renderer::drawRect(mHorizontalMargin, 0.0f, mSize.x - mHorizontalMargin * 2.0f, mSize.y,
0x00000033, 0x00000033);
Renderer::drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0x0000FF33, 0x0000FF33);
mRenderer->drawRect(mHorizontalMargin, 0.0f, mSize.x - mHorizontalMargin * 2.0f, mSize.y,
0x00000033, 0x00000033);
mRenderer->drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0x0000FF33, 0x0000FF33);
}
// 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.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)),
static_cast<int>(std::round(trans[3].y))},
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)
mLoopScroll = false;
Renderer::setMatrix(drawTrans);
mRenderer->setMatrix(drawTrans);
font->renderTextCache(entry.data.textCache.get());
// 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 = glm::translate(
drawTrans, offset - glm::vec3 {static_cast<float>(mLoopOffset2), 0.0f, 0.0f});
Renderer::setMatrix(drawTrans);
mRenderer->setMatrix(drawTrans);
font->renderTextCache(entry.data.textCache.get());
}
y += entrySize;
}
Renderer::popClipRect();
mRenderer->popClipRect();
List::listRenderTitleOverlay(trans);
GuiComponent::renderChildren(trans);
}

View file

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

View file

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

View file

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

View file

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

View file

@ -3,7 +3,7 @@
// EmulationStation Desktop Edition
// Renderer.cpp
//
// General rendering functions.
// Generic rendering functions.
//
#include "renderers/Renderer.h"
@ -12,468 +12,386 @@
#include "Log.h"
#include "Settings.h"
#include "Shader_GL21.h"
#include "renderers/Renderer_GL21.h"
#include "resources/ResourceManager.h"
#include <SDL2/SDL.h>
#include <stack>
#if defined(_WIN64)
#include <windows.h>
#endif
namespace Renderer
Renderer* Renderer::getInstance()
{
static std::stack<Rect> clipStack;
static SDL_Window* sdlWindow {nullptr};
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 RendererOpenGL instance;
return &instance;
}
static void setIcon()
{
size_t width {0};
size_t height {0};
ResourceData resData {
ResourceManager::getInstance().getFileData(":/graphics/window_icon_256.png")};
std::vector<unsigned char> rawData {
ImageIO::loadFromMemoryRGBA32(resData.ptr.get(), resData.length, width, height)};
void Renderer::setIcon()
{
size_t width {0};
size_t height {0};
ResourceData resData {
ResourceManager::getInstance().getFileData(":/graphics/window_icon_256.png")};
std::vector<unsigned char> rawData {
ImageIO::loadFromMemoryRGBA32(resData.ptr.get(), resData.length, width, height)};
if (!rawData.empty()) {
ImageIO::flipPixelsVert(rawData.data(), width, height);
if (!rawData.empty()) {
ImageIO::flipPixelsVert(rawData.data(), width, height);
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
unsigned int rmask {0xFF000000};
unsigned int gmask {0x00FF0000};
unsigned int bmask {0x0000FF00};
unsigned int amask {0x000000FF};
unsigned int rmask {0xFF000000};
unsigned int gmask {0x00FF0000};
unsigned int bmask {0x0000FF00};
unsigned int amask {0x000000FF};
#else
unsigned int rmask {0x000000FF};
unsigned int gmask {0x0000FF00};
unsigned int bmask {0x00FF0000};
unsigned int amask {0xFF000000};
unsigned int rmask {0x000000FF};
unsigned int gmask {0x0000FF00};
unsigned int bmask {0x00FF0000};
unsigned int amask {0xFF000000};
#endif
// Try creating SDL surface from logo data.
SDL_Surface* logoSurface {SDL_CreateRGBSurfaceFrom(
static_cast<void*>(rawData.data()), static_cast<int>(width),
static_cast<int>(height), 32, static_cast<int>((width * 4)), rmask, gmask, bmask,
amask)};
// Try creating SDL surface from logo data.
SDL_Surface* logoSurface {SDL_CreateRGBSurfaceFrom(
static_cast<void*>(rawData.data()), static_cast<int>(width), static_cast<int>(height),
32, static_cast<int>((width * 4)), rmask, gmask, bmask, amask)};
if (logoSurface != nullptr) {
SDL_SetWindowIcon(sdlWindow, logoSurface);
SDL_FreeSurface(logoSurface);
}
if (logoSurface != nullptr) {
SDL_SetWindowIcon(mSDLWindow, logoSurface);
SDL_FreeSurface(logoSurface);
}
}
}
static bool createWindow()
{
LOG(LogInfo) << "Creating window...";
bool Renderer::createWindow()
{
LOG(LogInfo) << "Creating window...";
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
LOG(LogError) << "Couldn't initialize SDL: " << SDL_GetError();
return false;
}
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
LOG(LogError) << "Couldn't initialize SDL: " << SDL_GetError();
return false;
}
initialCursorState = (SDL_ShowCursor(0) != 0);
mInitialCursorState = (SDL_ShowCursor(0) != 0);
int displayIndex {Settings::getInstance()->getInt("DisplayIndex")};
// 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) {
Settings::getInstance()->setInt("DisplayIndex", 1);
displayIndex = 0;
}
else {
--displayIndex;
}
int displayIndex {Settings::getInstance()->getInt("DisplayIndex")};
// 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) {
Settings::getInstance()->setInt("DisplayIndex", 1);
displayIndex = 0;
}
else {
--displayIndex;
}
int availableDisplays = SDL_GetNumVideoDisplays();
if (displayIndex > availableDisplays - 1) {
LOG(LogWarning) << "Requested display " << std::to_string(displayIndex + 1)
<< " does not exist, changing to display 1";
displayIndex = 0;
}
else {
LOG(LogInfo) << "Using display: " << std::to_string(displayIndex + 1);
}
int availableDisplays = SDL_GetNumVideoDisplays();
if (displayIndex > availableDisplays - 1) {
LOG(LogWarning) << "Requested display " << std::to_string(displayIndex + 1)
<< " does not exist, changing to display 1";
displayIndex = 0;
}
else {
LOG(LogInfo) << "Using display: " << std::to_string(displayIndex + 1);
}
SDL_DisplayMode displayMode;
SDL_GetDesktopDisplayMode(displayIndex, &displayMode);
SDL_DisplayMode displayMode;
SDL_GetDesktopDisplayMode(displayIndex, &displayMode);
#if defined(_WIN64)
// Tell Windows that we're DPI aware so that we can set a physical resolution and
// avoid any automatic DPI scaling.
SetProcessDPIAware();
// 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
// therefore do not necessarily reflect the physical display resolution.
SDL_Rect displayBounds;
SDL_GetDisplayBounds(displayIndex, &displayBounds);
displayMode.w = displayBounds.w;
displayMode.h = displayBounds.h;
// Tell Windows that we're DPI aware so that we can set a physical resolution and
// avoid any automatic DPI scaling.
SetProcessDPIAware();
// 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
// therefore do not necessarily reflect the physical display resolution.
SDL_Rect displayBounds;
SDL_GetDisplayBounds(displayIndex, &displayBounds);
displayMode.w = displayBounds.w;
displayMode.h = displayBounds.h;
#endif
windowWidth = Settings::getInstance()->getInt("WindowWidth") ?
Settings::getInstance()->getInt("WindowWidth") :
displayMode.w;
windowHeight = Settings::getInstance()->getInt("WindowHeight") ?
Settings::getInstance()->getInt("WindowHeight") :
displayMode.h;
screenWidth = Settings::getInstance()->getInt("ScreenWidth") ?
Settings::getInstance()->getInt("ScreenWidth") :
windowWidth;
screenHeight = Settings::getInstance()->getInt("ScreenHeight") ?
Settings::getInstance()->getInt("ScreenHeight") :
windowHeight;
screenOffsetX = Settings::getInstance()->getInt("ScreenOffsetX") ?
Settings::getInstance()->getInt("ScreenOffsetX") :
0;
screenOffsetY = Settings::getInstance()->getInt("ScreenOffsetY") ?
Settings::getInstance()->getInt("ScreenOffsetY") :
0;
screenRotated = Settings::getInstance()->getBool("ScreenRotate");
mWindowWidth = Settings::getInstance()->getInt("WindowWidth") ?
Settings::getInstance()->getInt("WindowWidth") :
displayMode.w;
mWindowHeight = Settings::getInstance()->getInt("WindowHeight") ?
Settings::getInstance()->getInt("WindowHeight") :
displayMode.h;
sScreenWidth = Settings::getInstance()->getInt("ScreenWidth") ?
Settings::getInstance()->getInt("ScreenWidth") :
mWindowWidth;
sScreenHeight = Settings::getInstance()->getInt("ScreenHeight") ?
Settings::getInstance()->getInt("ScreenHeight") :
mWindowHeight;
mScreenOffsetX = Settings::getInstance()->getInt("ScreenOffsetX") ?
Settings::getInstance()->getInt("ScreenOffsetX") :
0;
mScreenOffsetY = Settings::getInstance()->getInt("ScreenOffsetY") ?
Settings::getInstance()->getInt("ScreenOffsetY") :
0;
mScreenRotated = Settings::getInstance()->getBool("ScreenRotate");
// Prevent the application window from minimizing when switching windows (when launching
// games or when manually switching windows using the task switcher).
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
// Prevent the application window from minimizing when switching windows (when launching
// games or when manually switching windows using the task switcher).
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
#if defined(__unix__)
// 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
// the desktop.
if (Settings::getInstance()->getBool("DisableComposition"))
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "1");
else
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
// 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
// the desktop.
if (Settings::getInstance()->getBool("DisableComposition"))
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "1");
else
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
#endif
bool userResolution = false;
// Check if the user has changed the resolution from the command line.
if (windowWidth != displayMode.w || windowHeight != displayMode.h)
userResolution = true;
bool userResolution = false;
// Check if the user has changed the resolution from the command line.
if (mWindowWidth != displayMode.w || mWindowHeight != displayMode.h)
userResolution = true;
unsigned int windowFlags;
setupWindow();
unsigned int windowFlags;
setup();
#if defined(_WIN64)
// 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
// with a hidden taskbar.
if (!userResolution)
windowFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_OPENGL;
else
// If the resolution has been manually set from the command line, then keep the border.
windowFlags = SDL_WINDOW_OPENGL;
// 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
// with a hidden taskbar.
if (!userResolution)
windowFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_OPENGL;
else
// If the resolution has been manually set from the command line, then keep the border.
windowFlags = SDL_WINDOW_OPENGL;
#elif defined(__APPLE__)
// Not sure if this could be a useful setting.
// SDL_SetHint(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, "0");
// Not sure if this could be a useful setting.
// 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
// 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
// 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
// configured to run in fullscreen mode or switching to its window will not work, but
// apart from that this mode works fine.
if (!userResolution)
windowFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_OPENGL;
else
windowFlags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_OPENGL;
// 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
// 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
// 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
// apart from that this mode works fine.
if (!userResolution)
windowFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_OPENGL;
else
windowFlags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_OPENGL;
#else
if (!userResolution)
windowFlags = SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_OPENGL;
else
windowFlags = SDL_WINDOW_OPENGL;
if (!userResolution)
windowFlags = SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_OPENGL;
else
windowFlags = SDL_WINDOW_OPENGL;
#endif
if ((sdlWindow =
SDL_CreateWindow("EmulationStation", SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex),
SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), windowWidth,
windowHeight, windowFlags)) == nullptr) {
LOG(LogError) << "Couldn't create SDL window. " << SDL_GetError();
return false;
}
if ((mSDLWindow =
SDL_CreateWindow("EmulationStation", SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex),
SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex), mWindowWidth,
mWindowHeight, windowFlags)) == nullptr) {
LOG(LogError) << "Couldn't create SDL window. " << SDL_GetError();
return false;
}
#if defined(__APPLE__)
// 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
// 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
// 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
// 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,
// 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
// display so that the full application window is used for rendering.
int width = 0;
SDL_GL_GetDrawableSize(sdlWindow, &width, nullptr);
int scaleFactor = static_cast<int>(width / windowWidth);
// 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
// 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
// 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
// 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,
// 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
// display so that the full application window is used for rendering.
int width = 0;
SDL_GL_GetDrawableSize(mSDLWindow, &width, nullptr);
int scaleFactor = static_cast<int>(width / mWindowWidth);
LOG(LogInfo) << "Display resolution: " << std::to_string(displayMode.w) << "x"
<< std::to_string(displayMode.h) << " (physical resolution "
<< std::to_string(displayMode.w * scaleFactor) << "x"
<< std::to_string(displayMode.h * scaleFactor) << ")";
LOG(LogInfo) << "Display refresh rate: " << std::to_string(displayMode.refresh_rate)
<< " Hz";
LOG(LogInfo) << "EmulationStation resolution: " << std::to_string(windowWidth) << "x"
<< std::to_string(windowHeight) << " (physical resolution "
<< std::to_string(windowWidth * scaleFactor) << "x"
<< std::to_string(windowHeight * scaleFactor) << ")";
LOG(LogInfo) << "Display resolution: " << std::to_string(displayMode.w) << "x"
<< std::to_string(displayMode.h) << " (physical resolution "
<< std::to_string(displayMode.w * scaleFactor) << "x"
<< std::to_string(displayMode.h * scaleFactor) << ")";
LOG(LogInfo) << "Display refresh rate: " << std::to_string(displayMode.refresh_rate) << " Hz";
LOG(LogInfo) << "EmulationStation resolution: " << std::to_string(mWindowWidth) << "x"
<< std::to_string(mWindowHeight) << " (physical resolution "
<< std::to_string(mWindowWidth * scaleFactor) << "x"
<< std::to_string(mWindowHeight * scaleFactor) << ")";
windowWidth *= scaleFactor;
windowHeight *= scaleFactor;
screenWidth *= scaleFactor;
screenHeight *= scaleFactor;
mWindowWidth *= scaleFactor;
mWindowHeight *= scaleFactor;
sScreenWidth *= scaleFactor;
sScreenHeight *= scaleFactor;
#else
LOG(LogInfo) << "Display resolution: " << std::to_string(displayMode.w) << "x"
<< std::to_string(displayMode.h);
LOG(LogInfo) << "Display refresh rate: " << std::to_string(displayMode.refresh_rate)
<< " Hz";
LOG(LogInfo) << "EmulationStation resolution: " << std::to_string(windowWidth) << "x"
<< std::to_string(windowHeight);
LOG(LogInfo) << "Display resolution: " << std::to_string(displayMode.w) << "x"
<< std::to_string(displayMode.h);
LOG(LogInfo) << "Display refresh rate: " << std::to_string(displayMode.refresh_rate) << " Hz";
LOG(LogInfo) << "EmulationStation resolution: " << std::to_string(mWindowWidth) << "x"
<< std::to_string(mWindowHeight);
#endif
screenHeightModifier = static_cast<float>(screenHeight) / 1080.0f;
screenWidthModifier = static_cast<float>(screenWidth) / 1920.0f;
screenAspectRatio = static_cast<float>(screenWidth) / static_cast<float>(screenHeight);
sScreenHeightModifier = static_cast<float>(sScreenHeight) / 1080.0f;
sScreenWidthModifier = static_cast<float>(sScreenWidth) / 1920.0f;
sScreenAspectRatio = static_cast<float>(sScreenWidth) / static_cast<float>(sScreenHeight);
LOG(LogInfo) << "Setting up OpenGL...";
LOG(LogInfo) << "Setting up OpenGL...";
if (!createContext())
return false;
if (!createContext())
return false;
setIcon();
setSwapInterval();
setIcon();
setSwapInterval();
#if defined(_WIN64)
// 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
// in init() to work around the white screen flash issue on all operating systems.
swapBuffers();
// 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
// in init() to work around the white screen flash issue on all operating systems.
swapBuffers();
#endif
LOG(LogInfo) << "Loading shaders...";
return loadShaders();
}
std::vector<std::string> shaderFiles;
shaderFiles.push_back(":/shaders/glsl/core.glsl");
shaderFiles.push_back(":/shaders/glsl/blur_horizontal.glsl");
shaderFiles.push_back(":/shaders/glsl/blur_vertical.glsl");
shaderFiles.push_back(":/shaders/glsl/scanlines.glsl");
void Renderer::destroyWindow()
{
destroyContext();
SDL_DestroyWindow(mSDLWindow);
for (auto it = shaderFiles.cbegin(); it != shaderFiles.cend(); ++it) {
Shader* loadShader = new Shader();
mSDLWindow = nullptr;
loadShader->loadShaderFile(*it, GL_VERTEX_SHADER);
loadShader->loadShaderFile(*it, GL_FRAGMENT_SHADER);
SDL_ShowCursor(mInitialCursorState);
SDL_Quit();
}
if (!loadShader->createProgram()) {
LOG(LogError) << "Could not create shader program.";
return false;
}
bool Renderer::init()
{
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()
{
for (auto it = sShaderProgramVector.cbegin(); it != sShaderProgramVector.cend(); ++it)
delete *it;
destroyContext();
SDL_DestroyWindow(sdlWindow);
sdlWindow = nullptr;
SDL_ShowCursor(initialCursorState);
SDL_Quit();
// Make sure the box fits within mClipStack.top(), and clip further accordingly.
if (mClipStack.size()) {
const Rect& top {mClipStack.top()};
if (top.x > box.x)
box.x = top.x;
if (top.y > box.y)
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;
}
bool init()
{
if (!createWindow())
return false;
if (box.w < 0)
box.w = 0;
if (box.h < 0)
box.h = 0;
glm::mat4 projection {getIdentity()};
Rect viewport {0, 0, 0, 0};
mClipStack.push(box);
viewport.x = windowWidth - screenOffsetX - screenWidth;
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});
setScissor(box);
}
viewport.x = screenOffsetX;
viewport.y = screenOffsetY;
viewport.w = screenWidth;
viewport.h = screenHeight;
mProjectionMatrix = glm::ortho(0.0f, static_cast<float>(screenWidth),
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 Renderer::popClipRect()
{
if (mClipStack.empty()) {
LOG(LogError) << "Tried to popClipRect while the stack was empty";
return;
}
void deinit()
{
// Destroy the window.
destroyWindow();
}
mClipStack.pop();
void pushClipRect(const glm::ivec2& pos, const glm::ivec2& size)
{
Rect box(pos.x, pos.y, size.x, size.y);
if (mClipStack.empty())
setScissor(Rect(0, 0, 0, 0));
else
setScissor(mClipStack.top());
}
if (box.w == 0)
box.w = screenWidth - box.x;
if (box.h == 0)
box.h = screenHeight - box.y;
void Renderer::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 BlendFactor srcBlendFactorFactor,
const BlendFactor dstBlendFactorFactor)
{
Vertex vertices[4];
if (screenRotated) {
box = Rect(windowWidth - screenOffsetX - box.x - box.w,
windowHeight - screenOffsetY - box.y - box.h, box.w, box.h);
}
else {
box = Rect(screenOffsetX + box.x, screenOffsetY + box.y, box.w, box.h);
}
float wL {w};
float hL {h};
// Make sure the box fits within clipStack.top(), and clip further accordingly.
if (clipStack.size()) {
const Rect& top = clipStack.top();
if (top.x > box.x)
box.x = top.x;
if (top.y > box.y)
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 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;
if (box.w < 0)
box.w = 0;
if (box.h < 0)
box.h = 0;
// 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
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()
{
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
bindTexture(0);
drawTriangleStrips(vertices, 4, srcBlendFactorFactor, dstBlendFactorFactor);
}

View file

@ -3,123 +3,25 @@
// EmulationStation Desktop Edition
// Renderer.h
//
// General rendering functions.
// Generic rendering functions.
//
#ifndef ES_CORE_RENDERER_RENDERER_H
#define ES_CORE_RENDERER_RENDERER_H
#include "Log.h"
#include "Shader_GL21.h"
#include "utils/MathUtil.h"
#include <stack>
#include <string>
#include <vector>
struct SDL_Window;
class Shader;
namespace Renderer
class Renderer
{
// clang-format off
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;
};
public:
struct Vertex {
glm::vec2 position;
glm::vec2 texture;
@ -142,6 +44,7 @@ namespace Renderer
, shaders {0}
{
}
Vertex(const glm::vec2& position, const glm::vec2& textureCoord, const unsigned int color)
: position(position)
, 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();
void deinit();
virtual bool loadShaders() = 0;
void pushClipRect(const glm::ivec2& pos, const glm::ivec2& size);
void popClipRect();
void drawRect(const float x,
const float y,
const float w,
@ -170,56 +134,87 @@ namespace Renderer
bool horizontalGradient = false,
const float opacity = 1.0,
const float dimming = 1.0,
const Blend::Factor srcBlendFactor = Blend::SRC_ALPHA,
const Blend::Factor dstBlendFactor = Blend::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();
const BlendFactor srcBlendFactor = BlendFactor::SRC_ALPHA,
const BlendFactor dstBlendFactor = BlendFactor::ONE_MINUS_SRC_ALPHA);
Shader* getShaderProgram(unsigned int shaderID);
const glm::mat4& getProjectionMatrix();
const glm::mat4& getProjectionMatrixNormal();
void shaderPostprocessing(
const glm::mat4& getProjectionMatrix()
{
if (mScreenRotated)
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 Renderer::postProcessingParams& parameters = postProcessingParams(),
unsigned char* textureRGBA = nullptr);
unsigned char* textureRGBA = nullptr) = 0;
void setupWindow();
bool createContext();
void destroyContext();
unsigned int createTexture(const Texture::Type type,
const bool linearMinify,
const bool linearMagnify,
const bool repeat,
virtual void setup() = 0;
virtual bool createContext() = 0;
virtual void destroyContext() = 0;
virtual 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) = 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 height,
void* data);
void destroyTexture(const unsigned int texture);
void updateTexture(const unsigned int texture,
const Texture::Type type,
const unsigned int x,
const unsigned int y,
const unsigned int width,
const unsigned int height,
void* data);
void bindTexture(const unsigned int texture);
void drawTriangleStrips(const Vertex* vertices,
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();
void* data) = 0;
virtual void bindTexture(const unsigned int texture) = 0;
virtual void drawTriangleStrips(
const Vertex* vertices,
const unsigned int numVertices,
const BlendFactor srcBlendFactor = BlendFactor::SRC_ALPHA,
const BlendFactor dstBlendFactor = BlendFactor::ONE_MINUS_SRC_ALPHA) = 0;
virtual void setMatrix(const glm::mat4& matrix) = 0;
virtual void setScissor(const Rect& scissor) = 0;
virtual void setSwapInterval() = 0;
virtual void swapBuffers() = 0;
} // 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

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 "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()
{
// Delete the shader program when destroyed.
deleteProgram(mProgramID);
}
Shader::~Shader()
{
// Delete the shader program when destroyed.
deleteProgram(mProgramID);
}
void Renderer::Shader::loadShaderFile(const std::string& path, GLenum shaderType)
{
std::string preprocessorDefines;
std::string shaderCode;
void Shader::loadShaderFile(const std::string& path, GLenum shaderType)
{
std::string preprocessorDefines;
std::string shaderCode;
// This will load the entire GLSL source code into the string variable.
const ResourceData& shaderData {ResourceManager::getInstance().getFileData(path)};
shaderCode.assign(reinterpret_cast<const char*>(shaderData.ptr.get()), shaderData.length);
// This will load the entire GLSL source code into the string variable.
const ResourceData& shaderData {ResourceManager::getInstance().getFileData(path)};
shaderCode.assign(reinterpret_cast<const char*>(shaderData.ptr.get()), shaderData.length);
// Define the GLSL version.
// Define the GLSL version.
#if defined(USE_OPENGLES)
preprocessorDefines = "#version 300 es\n";
preprocessorDefines = "#version 300 es\n";
#else
preprocessorDefines = "#version 330\n";
preprocessorDefines = "#version 330\n";
#endif
// Define the preprocessor constants that will let the shader compiler know whether
// the VERTEX or FRAGMENT portion of the code should be used.
if (shaderType == GL_VERTEX_SHADER)
preprocessorDefines += "#define VERTEX\n";
else if (shaderType == GL_FRAGMENT_SHADER)
preprocessorDefines += "#define FRAGMENT\n";
// Define the preprocessor constants that will let the shader compiler know whether
// the VERTEX or FRAGMENT portion of the code should be used.
if (shaderType == GL_VERTEX_SHADER)
preprocessorDefines += "#define VERTEX\n";
else if (shaderType == GL_FRAGMENT_SHADER)
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()
{
GLint programSuccess;
bool Shader::createProgram()
{
GLint programSuccess;
mProgramID = glCreateProgram();
mProgramID = glCreateProgram();
// Compile and attach all shaders that have been loaded.
for (auto it = shaderVector.cbegin(); it != shaderVector.cend(); ++it) {
GLuint currentShader = glCreateShader(std::get<2>(*it));
GLchar const* shaderCodePtr = std::get<1>(*it).c_str();
// Compile and attach all shaders that have been loaded.
for (auto it = mShaderVector.cbegin(); it != mShaderVector.cend(); ++it) {
GLuint currentShader {glCreateShader(std::get<2>(*it))};
GLchar const* shaderCodePtr {std::get<1>(*it).c_str()};
glShaderSource(currentShader, 1, reinterpret_cast<const GLchar**>(&shaderCodePtr),
nullptr);
glCompileShader(currentShader);
glShaderSource(currentShader, 1, reinterpret_cast<const GLchar**>(&shaderCodePtr), nullptr);
glCompileShader(currentShader);
GLint shaderCompiled;
glGetShaderiv(currentShader, GL_COMPILE_STATUS, &shaderCompiled);
GLint shaderCompiled;
glGetShaderiv(currentShader, GL_COMPILE_STATUS, &shaderCompiled);
if (shaderCompiled != GL_TRUE) {
LOG(LogError) << "OpenGL error: Unable to compile shader " << currentShader << " ("
<< std::get<0>(*it) << ").";
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);
if (shaderCompiled != GL_TRUE) {
LOG(LogError) << "OpenGL error: Unable to compile shader " << currentShader << " ("
<< std::get<0>(*it) << ").";
printShaderInfoLog(currentShader, std::get<2>(*it), true);
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 {
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)
{
if (glIsShader(shaderID)) {
int logLength;
int maxLength;
glLinkProgram(mProgramID);
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.";
}
glGetProgramiv(mProgramID, GL_LINK_STATUS, &programSuccess);
if (programSuccess != GL_TRUE) {
LOG(LogError) << "OpenGL error: Unable to link program " << mProgramID << ".";
printProgramInfoLog(mProgramID);
return false;
}
} // 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
#include "renderers/Renderer.h"
#include "utils/MathUtil.h"
#if defined(_WIN64)
@ -28,61 +29,77 @@
#include <string>
#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
{
public:
Shader();
~Shader();
const GLenum errorCode = glGetError();
// Loads the shader source code only, no compilation done at this point.
void loadShaderFile(const std::string& path, GLenum shaderType);
// 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);
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
void setAttribPointers();
void setTextureSize(std::array<GLfloat, 2> shaderVec2);
void setOpacity(GLfloat opacity);
void setSaturation(GLfloat saturation);
void setDimming(GLfloat dimming);
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);
class Shader
{
public:
Shader();
~Shader();
private:
GLuint mProgramID;
std::vector<std::tuple<std::string, std::string, GLenum>> shaderVector;
// Loads the shader source code only, no compilation done at this point.
void loadShaderFile(const std::string& path, GLenum shaderType);
// 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.
GLint shaderMVPMatrix;
GLint shaderPosition;
GLint shaderTextureCoord;
GLint shaderColor;
GLint shaderTextureSize;
GLint shaderOpacity;
GLint shaderSaturation;
GLint shaderDimming;
GLint shaderBGRAToRGBA;
GLint shaderFont;
GLint shaderPostProcessing;
};
void setAttribPointers();
void setTextureSize(std::array<GLfloat, 2> shaderVec2);
void setOpacity(GLfloat opacity);
void setSaturation(GLfloat saturation);
void setDimming(GLfloat dimming);
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);
} // 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

View file

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

View file

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

View file

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

View file

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