From cac43474aa6f743bb47b532d18131d639d90af2b Mon Sep 17 00:00:00 2001 From: Aloshi Date: Tue, 4 Sep 2012 11:45:16 -0500 Subject: [PATCH] Fixed reinitialization problems with the renderer. --- CREDITS.md | 13 +++++-------- README.md | 14 +++++++------- THEMES.md | 2 -- changelog.txt | 3 +++ src/Font.cpp | 23 ++++++++++++----------- src/GuiComponent.cpp | 19 +++++++++++++++++++ src/GuiComponent.h | 5 +++++ src/Renderer.cpp | 16 ++++++++++++++++ src/Renderer.h | 2 ++ src/Renderer_draw_gl.cpp | 21 +++++++++++++++++++-- src/Renderer_init_rpi.cpp | 19 ++++++++++++------- src/SystemData.cpp | 3 +-- src/components/GuiGameList.cpp | 12 +++++++++++- src/components/GuiGameList.h | 2 ++ src/components/GuiImage.cpp | 29 +++++++++++++++++++---------- src/components/GuiImage.h | 6 ++++-- src/components/GuiTheme.cpp | 4 +--- src/main.cpp | 6 ++++++ 18 files changed, 144 insertions(+), 55 deletions(-) diff --git a/CREDITS.md b/CREDITS.md index 1e7f5c61f..841da4fc0 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -5,7 +5,7 @@ Programming Resources ========= -LinLibertine.ttf +LinLibertine_R.ttf The Libertine Font Project - http://www.linuxlibertine.org/ PugiXML @@ -14,11 +14,8 @@ PugiXML SDL 1.2 http://www.libsdl.org/ -SDL TTF - http://www.libsdl.org/projects/SDL_ttf/ +FreeImage + http://www.freeimage.sourceforge.net -SDL_image - http://www.libsdl.org/projects/SDL_image/ - -SDL_gfx - http://sourceforge.net/projects/sdlgfx/ +FreeType + http://www.freetype.org diff --git a/README.md b/README.md index ca5212373..bfc0885d8 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,22 @@ EmulationStation ================ -A simple front-end for emulators made with SDL, designed for controller navigation. Developed for use with the Raspberry Pi and RetroArch, though it can easily be used for other things. +A graphical front-end for emulators with controller navigation. Developed both on and for the Raspbery Pi. Intended for use with RetroArch, but it can easily be used with other emulators. RetroArch for the Raspberry Pi can be found here: https://github.com/ToadKing/RetroArch-Rpi I'm not associated with RetroArch in any way! -If you're lazy, a cool guy named petrockblog made a script which automatically installs RetroArch, its cores, and ES: https://github.com/petrockblog/RetroPie-Setup +A cool guy named petrockblog made a script which automatically installs RetroArch, its cores, and ES. It also includes options for configuring your RPi and setting it up to boot directly into ES. You can find it here: https://github.com/petrockblog/RetroPie-Setup Building ======== -EmulationStation has quite a few dependencies. For building, you'll need SDL 1.2, the SDL TTF library, the SDL image library, the SDL_gfx library, and Boost.Filesystem, which can easily be obtained with apt-get: +EmulationStation has a few dependencies. For building, you'll need SDL 1.2, FreeImage, FreeType, and Boost.Filesystem, which can easily be obtained with apt-get: ``` -sudo apt-get install libsdl1.2-dev libsdl-ttf2.0-dev libboost-filesystem-dev libsdl-image1.2-dev libsdl-gfx1.2-dev +sudo apt-get install libsdl1.2-dev libboost-filesystem-dev libfreeimage-dev libfreetype6-dev ``` -You can build EmulationStation by simply running `make`. +There are also a few libraries already on the RPi (located in /opt/vc/, like the Broadcom libraries, EGL, and GLES). You can build EmulationStation by simply running `make`. Configuring =========== @@ -53,12 +53,12 @@ The path element should be the absolute path of the ROM. Special characters SHOU The switch `--gamelist-only` can be used to skip automatic searching, and only display games defined in the system's gamelist.xml. -A cool guy named Pendor made a scraper which automatically generates a gamelist.xml for you, with boxart automatically downloaded: https://github.com/jpzapa/ES-thegamesdb-scraper +**Making a gamelist.xml by hand sucks, so a cool guy named Pendor made a python script which automatically generates a gamelist.xml for you, with boxart automatically downloaded. I highly recommend it. It can be found here:** https://github.com/elpendor/ES-scraper Themes ====== -If you want to know more about themes, read THEMES.md! +By default, EmulationStation looks pretty ugly. You can fix that. If you want to know more, read THEMES.md! -Aloshi diff --git a/THEMES.md b/THEMES.md index 0189cf2fb..5837ee1eb 100644 --- a/THEMES.md +++ b/THEMES.md @@ -50,8 +50,6 @@ Used to display an image. `` - if present, the image is tiled instead of resized. Tiling isn't exact at the moment, but good enough for backgrounds. -`` - if present, the image will not be stripped of its alpha channel. It will render much slower, but should have transparency. - Display tags ============ diff --git a/changelog.txt b/changelog.txt index c0a9e16e9..265a33909 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +September 3 +-Everything is now rendered with OpenGL, leading to a (roughly) 600%+ speedup! + August 13 -Tons of new theming features! -I've added a THEMES.md file for documentation on theming. diff --git a/src/Font.cpp b/src/Font.cpp index ff0ad3616..df0889cf7 100644 --- a/src/Font.cpp +++ b/src/Font.cpp @@ -13,7 +13,7 @@ void Font::initLibrary() { if(FT_Init_FreeType(&sLibrary)) { - std::cout << "Error initializing FreeType!\n"; + std::cerr << "Error initializing FreeType!\n"; } } @@ -23,7 +23,7 @@ Font::Font(std::string path, int size) if(FT_New_Face(sLibrary, path.c_str(), 0, &face)) { - std::cout << "Error creating font face! (path: " << path.c_str() << "\n"; + std::cerr << "Error creating font face! (path: " << path.c_str() << "\n"; while(true); } @@ -100,9 +100,6 @@ void Font::buildAtlas() { x = 0; y += maxHeight; - - std::cout << "looping to next row, maxHeight: " << maxHeight << std::endl; - maxHeight = 0; } @@ -128,8 +125,7 @@ void Font::buildAtlas() glBindTexture(GL_TEXTURE_2D, 0); - std::cout << "generated texture \"" << textureID << "\" (w: " << w << " h: " << h << ")" << std::endl; - std::cout << "(final x: " << x << " y: " << y << ")" << std::endl; + //std::cout << "generated texture \"" << textureID << "\" (w: " << w << " h: " << h << ")" << std::endl; } Font::~Font() @@ -174,7 +170,8 @@ void Font::drawText(std::string text, int startx, int starty, int color) starty += mMaxGlyphHeight; //padding (another 0.5% is added to the bottom through the sizeText function) - starty += Renderer::getScreenHeight() * 0.005; + //starty += Renderer::getScreenHeight() * 0.01; + starty += mMaxGlyphHeight * 0.1; int pointCount = text.length() * 2; @@ -200,7 +197,7 @@ void Font::drawText(std::string text, int startx, int starty, int color) float y = starty; for(; p < pointCount; i++, p++) { - int letter = text[i]; + unsigned char letter = text[i]; if(letter < 32 || letter >= 128) continue; @@ -257,7 +254,11 @@ void Font::sizeText(std::string text, int* w, int* h) int cwidth = 0; for(unsigned int i = 0; i < text.length(); i++) { - cwidth += charData[(int)text[i]].advX; + unsigned char letter = text[i]; + if(letter < 32 || letter >= 128) + continue; + + cwidth += charData[letter].advX; } @@ -265,5 +266,5 @@ void Font::sizeText(std::string text, int* w, int* h) *w = cwidth; if(h != NULL) - *h = mMaxGlyphHeight + Renderer::getScreenWidth() * 0.01; + *h = mMaxGlyphHeight + mMaxGlyphHeight * 0.5; } diff --git a/src/GuiComponent.cpp b/src/GuiComponent.cpp index 6cbfafa0a..4f805d6ac 100644 --- a/src/GuiComponent.cpp +++ b/src/GuiComponent.cpp @@ -78,3 +78,22 @@ void GuiComponent::resume() mChildren.at(i)->resume(); } +void GuiComponent::init() +{ + onInit(); + + for(unsigned int i = 0; i < mChildren.size(); i++) + { + mChildren.at(i)->init(); + } +} + +void GuiComponent::deinit() +{ + onDeinit(); + + for(unsigned int i = 0; i < mChildren.size(); i++) + { + mChildren.at(i)->deinit(); + } +} diff --git a/src/GuiComponent.h b/src/GuiComponent.h index 7bc38e575..9ae56960f 100644 --- a/src/GuiComponent.h +++ b/src/GuiComponent.h @@ -20,6 +20,11 @@ public: virtual void onPause() { }; virtual void onResume() { }; + void init(); + void deinit(); + virtual void onInit() { }; + virtual void onDeinit() { }; + virtual void onInput(InputManager::InputButton button, bool keyDown) { }; void addChild(GuiComponent* comp); diff --git a/src/Renderer.cpp b/src/Renderer.cpp index 14e0b8905..909f5ad4f 100644 --- a/src/Renderer.cpp +++ b/src/Renderer.cpp @@ -36,3 +36,19 @@ void Renderer::render() renderVector.at(i)->render(); } } + +void Renderer::onInit() +{ + for(unsigned int i = 0; i < renderVector.size(); i++) + { + renderVector.at(i)->init(); + } +} + +void Renderer::onDeinit() +{ + for(unsigned int i = 0; i < renderVector.size(); i++) + { + renderVector.at(i)->deinit(); + } +} diff --git a/src/Renderer.h b/src/Renderer.h index 7f5a2fa6c..ac90cd7d8 100644 --- a/src/Renderer.h +++ b/src/Renderer.h @@ -14,7 +14,9 @@ namespace Renderer void deleteAll(); bool init(int w, int h); + void onInit(); void deinit(); + void onDeinit(); void render(); diff --git a/src/Renderer_draw_gl.cpp b/src/Renderer_draw_gl.cpp index 5ff23187f..de1012383 100644 --- a/src/Renderer_draw_gl.cpp +++ b/src/Renderer_draw_gl.cpp @@ -2,6 +2,7 @@ #include #include #include "Font.h" +#include namespace Renderer { bool loadedFonts = false; @@ -63,10 +64,23 @@ namespace Renderer { { std::cout << "loading fonts\n"; - unsigned int fontSizes[] = {10, 12, 22}; + std::string fontPath = "LinLibertine_R.ttf"; + + //make sure our font exists + if(!boost::filesystem::exists(fontPath)) + { + std::cout << "Default font \"" << fontPath << "\" does not exist! Attempting to default to a system font...\n"; + fontPath = "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf"; + if(!boost::filesystem::exists(fontPath)) + { + std::cerr << "System font \"" << fontPath << "\" wasn't found either! Well, you're kind of screwed. Sorry.\n"; + } + } + + float fontSizes[] = {0.004, 0.006, 0.009}; for(unsigned int i = 0; i < 3; i++) { - fonts[i] = new Font("LinLibertine_R.ttf", fontSizes[i]); + fonts[i] = new Font(fontPath, (unsigned int)(fontSizes[i] * getScreenWidth())); } loadedFonts = true; @@ -108,6 +122,9 @@ namespace Renderer { if(!loadedFonts) loadFonts(); + if(x < 0) + std::cout << "drawing at " << x << std::endl; + getFont(font)->drawText(text, x, y, color); } diff --git a/src/Renderer_init_rpi.cpp b/src/Renderer_init_rpi.cpp index 155c504e9..20df9ed37 100644 --- a/src/Renderer_init_rpi.cpp +++ b/src/Renderer_init_rpi.cpp @@ -1,3 +1,4 @@ +#include "Renderer.h" #include #include #include @@ -71,7 +72,6 @@ namespace Renderer std::cerr << "Error choosing config!\n"; return false; } - std::cout << "numConfigs: " << numConfigs << "\n"; context = eglCreateContext(display, config, EGL_NO_CONTEXT, NULL); @@ -97,7 +97,7 @@ namespace Renderer } } - std::cout << "Display size is " << display_width << "x" << display_height << "\n"; + std::cout << "Display size is " << display_width << "x" << display_height << ".\n"; dst_rect.x = 0; dst_rect.y = 0; @@ -133,7 +133,7 @@ namespace Renderer } - std::cout << "success!\n"; + std::cout << "Success!\n"; return true; } @@ -151,12 +151,14 @@ namespace Renderer eglDestroySurface(display, surface); eglDestroyContext(display, context); eglTerminate(display); + + display = EGL_NO_DISPLAY; + surface = EGL_NO_SURFACE; + context = EGL_NO_CONTEXT; } bool init(int w, int h) { - bcm_host_init(); - if(w) display_width = w; if(h) @@ -173,14 +175,17 @@ namespace Renderer glOrthof(0, display_width, display_height, 0, -1.0, 1.0); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + onInit(); + return true; } - void unloadFonts(); + void unloadFonts(); //defined in Renderer_draw_gl.cpp void deinit() { + onDeinit(); + unloadFonts(); destroySurface(); - bcm_host_deinit(); } }; diff --git a/src/SystemData.cpp b/src/SystemData.cpp index 54e0e1030..b199a90b3 100644 --- a/src/SystemData.cpp +++ b/src/SystemData.cpp @@ -167,7 +167,6 @@ void SystemData::loadConfig() lineValid = true; varName = line.substr(0, i); varValue = line.substr(i + 1, line.length() - 1); - std::cout << " " << varName << " = " << varValue << "\n"; break; } } @@ -184,7 +183,7 @@ void SystemData::loadConfig() else if(varName == "COMMAND") sysCommand = varValue; //else - // std::cerr << "Error reading config file - unknown variable name \"" << varName << "\"!\n"; + // std::cout << "Warning reading config file - unknown variable name \"" << varName << "\", ignoring.\n"; //we have all our variables - create the system object if(!sysName.empty() && !sysPath.empty() &&!sysExtension.empty() && !sysCommand.empty()) diff --git a/src/components/GuiGameList.cpp b/src/components/GuiGameList.cpp index dd2974aa2..f0daecd0b 100644 --- a/src/components/GuiGameList.cpp +++ b/src/components/GuiGameList.cpp @@ -95,7 +95,7 @@ void GuiGameList::onRender() ss << FRAMERATE; std::string fps; ss >> fps; - Renderer::drawText(fps, 100, 0, 0x00FF00); + Renderer::drawText(fps, 100, 50, 0x00FF00); #endif //header @@ -235,3 +235,13 @@ void GuiGameList::onResume() { InputManager::registerComponent(this); } + +void GuiGameList::onDeinit() +{ + mTheme->deinit(); +} + +void GuiGameList::onInit() +{ + mTheme->onInit(); +} diff --git a/src/components/GuiGameList.h b/src/components/GuiGameList.h index e2456b82c..88f9d4aa6 100644 --- a/src/components/GuiGameList.h +++ b/src/components/GuiGameList.h @@ -25,6 +25,8 @@ public: void onInput(InputManager::InputButton button, bool keyDown); void onPause(); void onResume(); + void onInit(); + void onDeinit(); static const float sInfoWidth; private: diff --git a/src/components/GuiImage.cpp b/src/components/GuiImage.cpp index 2e344376d..ec07ef5f5 100644 --- a/src/components/GuiImage.cpp +++ b/src/components/GuiImage.cpp @@ -25,7 +25,6 @@ GuiImage::GuiImage(int offsetX, int offsetY, std::string path, unsigned int resi mResizeHeight = resizeHeight; mResizeExact = resizeExact; - mUseAlpha = false; if(!path.empty()) setImage(path); @@ -45,6 +44,10 @@ void GuiImage::loadImage(std::string path) return; } + //make sure we don't already have an image + unloadImage(); + + FREE_IMAGE_FORMAT format = FIF_UNKNOWN; FIBITMAP* image = NULL; BYTE* imageData = NULL; @@ -64,9 +67,7 @@ void GuiImage::loadImage(std::string path) //make sure we can read this filetype first, then load it if(FreeImage_FIFSupportsReading(format)) { - std::cout << "Loading image..."; image = FreeImage_Load(format, path.c_str()); - std::cout << "success\n"; }else{ std::cerr << "Error - file format reading not supported for image \"" << path << "\"!\n"; return; @@ -162,14 +163,13 @@ void GuiImage::loadImage(std::string path) mHeight *= resizeScaleY; } - std::cout << "Image load successful, w: " << mWidth << " h: " << mHeight << " texID: " << mTextureID << "\n"; + //std::cout << "Image load successful, w: " << mWidth << " h: " << mHeight << " texID: " << mTextureID << "\n"; } void GuiImage::unloadImage() { if(mTextureID) { - std::cout << "deleting texture\n"; glDeleteTextures(1, &mTextureID); mTextureID = 0; @@ -203,11 +203,6 @@ void GuiImage::setTiling(bool tile) mResizeExact = false; } -void GuiImage::setAlpha(bool useAlpha) -{ - mUseAlpha = useAlpha; -} - void GuiImage::onRender() { if(mTextureID) @@ -232,6 +227,7 @@ void GuiImage::drawImage(int posX, int posY) glBindTexture(GL_TEXTURE_2D, mTextureID); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GLfloat points[12]; points[0] = posX - (mWidth * mOriginX); points[1] = posY - (mHeight * mOriginY); @@ -269,3 +265,16 @@ void GuiImage::drawImage(int posX, int posY) glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); } + +void GuiImage::onInit() +{ + if(!mPath.empty()) + { + loadImage(mPath); + } +} + +void GuiImage::onDeinit() +{ + unloadImage(); +} diff --git a/src/components/GuiImage.h b/src/components/GuiImage.h index feee6a0f5..81400b0ee 100644 --- a/src/components/GuiImage.h +++ b/src/components/GuiImage.h @@ -15,17 +15,19 @@ public: void setImage(std::string path); void setOrigin(float originX, float originY); void setTiling(bool tile); - void setAlpha(bool useAlpha); int getWidth(); int getHeight(); void onRender(); + void onInit(); + void onDeinit(); + private: unsigned int mResizeWidth, mResizeHeight; float mOriginX, mOriginY; - bool mResizeExact, mTiled, mUseAlpha; + bool mResizeExact, mTiled; void loadImage(std::string path); void drawImage(int x, int y); diff --git a/src/components/GuiTheme.cpp b/src/components/GuiTheme.cpp index 0c5e29ebf..d4ebc0aa4 100644 --- a/src/components/GuiTheme.cpp +++ b/src/components/GuiTheme.cpp @@ -114,7 +114,6 @@ GuiComponent* GuiTheme::createElement(pugi::xml_node data, GuiComponent* parent) std::string dim = data.child("dim").text().get(); std::string origin = data.child("origin").text().get(); - bool useAlpha = data.child("useAlpha"); bool tiled = data.child("tiled"); //split position and dimension information @@ -127,7 +126,7 @@ GuiComponent* GuiTheme::createElement(pugi::xml_node data, GuiComponent* parent) std::string originX, originY; splitString(origin, ' ', &originX, &originY); - std::cout << "image, x: " << posX << " y: " << posY << " w: " << dimW << " h: " << dimH << " ox: " << originX << " oy: " << originY << " alpha: " << useAlpha << " tiled: " << tiled << "\n"; + std::cout << "image, x: " << posX << " y: " << posY << " w: " << dimW << " h: " << dimH << " ox: " << originX << " oy: " << originY << " tiled: " << tiled << "\n"; //resolve to pixels from percentages/variables int x = resolveExp(posX) * Renderer::getScreenWidth(); @@ -142,7 +141,6 @@ GuiComponent* GuiTheme::createElement(pugi::xml_node data, GuiComponent* parent) GuiImage* comp = new GuiImage(x, y, "", w, h, true); comp->setOrigin(ox, oy); - comp->setAlpha(useAlpha); comp->setTiling(tiled); comp->setImage(path); diff --git a/src/main.cpp b/src/main.cpp index 32522fb12..bbc651caf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,6 +5,7 @@ #include #include "components/GuiInputConfig.h" #include +#include bool PARSEGAMELISTONLY = false; bool IGNOREGAMELIST = false; @@ -17,6 +18,8 @@ namespace fs = boost::filesystem; int main(int argc, char* argv[]) { + bcm_host_init(); + bool running = true; //by the way, if anyone ever tries to port this to a different renderer but leave SDL as input - @@ -187,5 +190,8 @@ int main(int argc, char* argv[]) std::cout << "EmulationStation cleanly shutting down...\n"; SDL_Quit(); + + bcm_host_deinit(); + return 0; }