Fixed reinitialization problems with the renderer.

This commit is contained in:
Aloshi 2012-09-04 11:45:16 -05:00
parent 07d8046a3e
commit cac43474aa
18 changed files with 144 additions and 55 deletions

View file

@ -5,7 +5,7 @@ Programming
Resources Resources
========= =========
LinLibertine.ttf LinLibertine_R.ttf
The Libertine Font Project - http://www.linuxlibertine.org/ The Libertine Font Project - http://www.linuxlibertine.org/
PugiXML PugiXML
@ -14,11 +14,8 @@ PugiXML
SDL 1.2 SDL 1.2
http://www.libsdl.org/ http://www.libsdl.org/
SDL TTF FreeImage
http://www.libsdl.org/projects/SDL_ttf/ http://www.freeimage.sourceforge.net
SDL_image FreeType
http://www.libsdl.org/projects/SDL_image/ http://www.freetype.org
SDL_gfx
http://sourceforge.net/projects/sdlgfx/

View file

@ -1,22 +1,22 @@
EmulationStation 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 RetroArch for the Raspberry Pi can be found here: https://github.com/ToadKing/RetroArch-Rpi
I'm not associated with RetroArch in any way! 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 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 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. 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 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 -Aloshi

View file

@ -50,8 +50,6 @@ Used to display an image.
`<tiled />` - if present, the image is tiled instead of resized. Tiling isn't exact at the moment, but good enough for backgrounds. `<tiled />` - if present, the image is tiled instead of resized. Tiling isn't exact at the moment, but good enough for backgrounds.
`<useAlpha />` - if present, the image will not be stripped of its alpha channel. It will render much slower, but should have transparency.
Display tags Display tags
============ ============

View file

@ -1,3 +1,6 @@
September 3
-Everything is now rendered with OpenGL, leading to a (roughly) 600%+ speedup!
August 13 August 13
-Tons of new theming features! -Tons of new theming features!
-I've added a THEMES.md file for documentation on theming. -I've added a THEMES.md file for documentation on theming.

View file

@ -13,7 +13,7 @@ void Font::initLibrary()
{ {
if(FT_Init_FreeType(&sLibrary)) 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)) 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); while(true);
} }
@ -100,9 +100,6 @@ void Font::buildAtlas()
{ {
x = 0; x = 0;
y += maxHeight; y += maxHeight;
std::cout << "looping to next row, maxHeight: " << maxHeight << std::endl;
maxHeight = 0; maxHeight = 0;
} }
@ -128,8 +125,7 @@ void Font::buildAtlas()
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
std::cout << "generated texture \"" << textureID << "\" (w: " << w << " h: " << h << ")" << std::endl; //std::cout << "generated texture \"" << textureID << "\" (w: " << w << " h: " << h << ")" << std::endl;
std::cout << "(final x: " << x << " y: " << y << ")" << std::endl;
} }
Font::~Font() Font::~Font()
@ -174,7 +170,8 @@ void Font::drawText(std::string text, int startx, int starty, int color)
starty += mMaxGlyphHeight; starty += mMaxGlyphHeight;
//padding (another 0.5% is added to the bottom through the sizeText function) //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; int pointCount = text.length() * 2;
@ -200,7 +197,7 @@ void Font::drawText(std::string text, int startx, int starty, int color)
float y = starty; float y = starty;
for(; p < pointCount; i++, p++) for(; p < pointCount; i++, p++)
{ {
int letter = text[i]; unsigned char letter = text[i];
if(letter < 32 || letter >= 128) if(letter < 32 || letter >= 128)
continue; continue;
@ -257,7 +254,11 @@ void Font::sizeText(std::string text, int* w, int* h)
int cwidth = 0; int cwidth = 0;
for(unsigned int i = 0; i < text.length(); i++) 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; *w = cwidth;
if(h != NULL) if(h != NULL)
*h = mMaxGlyphHeight + Renderer::getScreenWidth() * 0.01; *h = mMaxGlyphHeight + mMaxGlyphHeight * 0.5;
} }

View file

@ -78,3 +78,22 @@ void GuiComponent::resume()
mChildren.at(i)->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();
}
}

View file

@ -20,6 +20,11 @@ public:
virtual void onPause() { }; virtual void onPause() { };
virtual void onResume() { }; virtual void onResume() { };
void init();
void deinit();
virtual void onInit() { };
virtual void onDeinit() { };
virtual void onInput(InputManager::InputButton button, bool keyDown) { }; virtual void onInput(InputManager::InputButton button, bool keyDown) { };
void addChild(GuiComponent* comp); void addChild(GuiComponent* comp);

View file

@ -36,3 +36,19 @@ void Renderer::render()
renderVector.at(i)->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();
}
}

View file

@ -14,7 +14,9 @@ namespace Renderer
void deleteAll(); void deleteAll();
bool init(int w, int h); bool init(int w, int h);
void onInit();
void deinit(); void deinit();
void onDeinit();
void render(); void render();

View file

@ -2,6 +2,7 @@
#include <GLES/gl.h> #include <GLES/gl.h>
#include <iostream> #include <iostream>
#include "Font.h" #include "Font.h"
#include <boost/filesystem.hpp>
namespace Renderer { namespace Renderer {
bool loadedFonts = false; bool loadedFonts = false;
@ -63,10 +64,23 @@ namespace Renderer {
{ {
std::cout << "loading fonts\n"; 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++) 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; loadedFonts = true;
@ -108,6 +122,9 @@ namespace Renderer {
if(!loadedFonts) if(!loadedFonts)
loadFonts(); loadFonts();
if(x < 0)
std::cout << "drawing at " << x << std::endl;
getFont(font)->drawText(text, x, y, color); getFont(font)->drawText(text, x, y, color);
} }

View file

@ -1,3 +1,4 @@
#include "Renderer.h"
#include <bcm_host.h> #include <bcm_host.h>
#include <iostream> #include <iostream>
#include <bcm_host.h> #include <bcm_host.h>
@ -71,7 +72,6 @@ namespace Renderer
std::cerr << "Error choosing config!\n"; std::cerr << "Error choosing config!\n";
return false; return false;
} }
std::cout << "numConfigs: " << numConfigs << "\n";
context = eglCreateContext(display, config, EGL_NO_CONTEXT, NULL); 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; dst_rect.x = 0; dst_rect.y = 0;
@ -133,7 +133,7 @@ namespace Renderer
} }
std::cout << "success!\n"; std::cout << "Success!\n";
return true; return true;
} }
@ -151,12 +151,14 @@ namespace Renderer
eglDestroySurface(display, surface); eglDestroySurface(display, surface);
eglDestroyContext(display, context); eglDestroyContext(display, context);
eglTerminate(display); eglTerminate(display);
display = EGL_NO_DISPLAY;
surface = EGL_NO_SURFACE;
context = EGL_NO_CONTEXT;
} }
bool init(int w, int h) bool init(int w, int h)
{ {
bcm_host_init();
if(w) if(w)
display_width = w; display_width = w;
if(h) if(h)
@ -173,14 +175,17 @@ namespace Renderer
glOrthof(0, display_width, display_height, 0, -1.0, 1.0); glOrthof(0, display_width, display_height, 0, -1.0, 1.0);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
onInit();
return true; return true;
} }
void unloadFonts(); void unloadFonts(); //defined in Renderer_draw_gl.cpp
void deinit() void deinit()
{ {
onDeinit();
unloadFonts(); unloadFonts();
destroySurface(); destroySurface();
bcm_host_deinit();
} }
}; };

View file

@ -167,7 +167,6 @@ void SystemData::loadConfig()
lineValid = true; lineValid = true;
varName = line.substr(0, i); varName = line.substr(0, i);
varValue = line.substr(i + 1, line.length() - 1); varValue = line.substr(i + 1, line.length() - 1);
std::cout << " " << varName << " = " << varValue << "\n";
break; break;
} }
} }
@ -184,7 +183,7 @@ void SystemData::loadConfig()
else if(varName == "COMMAND") else if(varName == "COMMAND")
sysCommand = varValue; sysCommand = varValue;
//else //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 //we have all our variables - create the system object
if(!sysName.empty() && !sysPath.empty() &&!sysExtension.empty() && !sysCommand.empty()) if(!sysName.empty() && !sysPath.empty() &&!sysExtension.empty() && !sysCommand.empty())

View file

@ -95,7 +95,7 @@ void GuiGameList::onRender()
ss << FRAMERATE; ss << FRAMERATE;
std::string fps; std::string fps;
ss >> fps; ss >> fps;
Renderer::drawText(fps, 100, 0, 0x00FF00); Renderer::drawText(fps, 100, 50, 0x00FF00);
#endif #endif
//header //header
@ -235,3 +235,13 @@ void GuiGameList::onResume()
{ {
InputManager::registerComponent(this); InputManager::registerComponent(this);
} }
void GuiGameList::onDeinit()
{
mTheme->deinit();
}
void GuiGameList::onInit()
{
mTheme->onInit();
}

View file

@ -25,6 +25,8 @@ public:
void onInput(InputManager::InputButton button, bool keyDown); void onInput(InputManager::InputButton button, bool keyDown);
void onPause(); void onPause();
void onResume(); void onResume();
void onInit();
void onDeinit();
static const float sInfoWidth; static const float sInfoWidth;
private: private:

View file

@ -25,7 +25,6 @@ GuiImage::GuiImage(int offsetX, int offsetY, std::string path, unsigned int resi
mResizeHeight = resizeHeight; mResizeHeight = resizeHeight;
mResizeExact = resizeExact; mResizeExact = resizeExact;
mUseAlpha = false;
if(!path.empty()) if(!path.empty())
setImage(path); setImage(path);
@ -45,6 +44,10 @@ void GuiImage::loadImage(std::string path)
return; return;
} }
//make sure we don't already have an image
unloadImage();
FREE_IMAGE_FORMAT format = FIF_UNKNOWN; FREE_IMAGE_FORMAT format = FIF_UNKNOWN;
FIBITMAP* image = NULL; FIBITMAP* image = NULL;
BYTE* imageData = 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 //make sure we can read this filetype first, then load it
if(FreeImage_FIFSupportsReading(format)) if(FreeImage_FIFSupportsReading(format))
{ {
std::cout << "Loading image...";
image = FreeImage_Load(format, path.c_str()); image = FreeImage_Load(format, path.c_str());
std::cout << "success\n";
}else{ }else{
std::cerr << "Error - file format reading not supported for image \"" << path << "\"!\n"; std::cerr << "Error - file format reading not supported for image \"" << path << "\"!\n";
return; return;
@ -162,14 +163,13 @@ void GuiImage::loadImage(std::string path)
mHeight *= resizeScaleY; 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() void GuiImage::unloadImage()
{ {
if(mTextureID) if(mTextureID)
{ {
std::cout << "deleting texture\n";
glDeleteTextures(1, &mTextureID); glDeleteTextures(1, &mTextureID);
mTextureID = 0; mTextureID = 0;
@ -203,11 +203,6 @@ void GuiImage::setTiling(bool tile)
mResizeExact = false; mResizeExact = false;
} }
void GuiImage::setAlpha(bool useAlpha)
{
mUseAlpha = useAlpha;
}
void GuiImage::onRender() void GuiImage::onRender()
{ {
if(mTextureID) if(mTextureID)
@ -232,6 +227,7 @@ void GuiImage::drawImage(int posX, int posY)
glBindTexture(GL_TEXTURE_2D, mTextureID); glBindTexture(GL_TEXTURE_2D, mTextureID);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GLfloat points[12]; GLfloat points[12];
points[0] = posX - (mWidth * mOriginX); points[1] = posY - (mHeight * mOriginY); 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_TEXTURE_2D);
glDisable(GL_BLEND); glDisable(GL_BLEND);
} }
void GuiImage::onInit()
{
if(!mPath.empty())
{
loadImage(mPath);
}
}
void GuiImage::onDeinit()
{
unloadImage();
}

View file

@ -15,17 +15,19 @@ public:
void setImage(std::string path); void setImage(std::string path);
void setOrigin(float originX, float originY); void setOrigin(float originX, float originY);
void setTiling(bool tile); void setTiling(bool tile);
void setAlpha(bool useAlpha);
int getWidth(); int getWidth();
int getHeight(); int getHeight();
void onRender(); void onRender();
void onInit();
void onDeinit();
private: private:
unsigned int mResizeWidth, mResizeHeight; unsigned int mResizeWidth, mResizeHeight;
float mOriginX, mOriginY; float mOriginX, mOriginY;
bool mResizeExact, mTiled, mUseAlpha; bool mResizeExact, mTiled;
void loadImage(std::string path); void loadImage(std::string path);
void drawImage(int x, int y); void drawImage(int x, int y);

View file

@ -114,7 +114,6 @@ GuiComponent* GuiTheme::createElement(pugi::xml_node data, GuiComponent* parent)
std::string dim = data.child("dim").text().get(); std::string dim = data.child("dim").text().get();
std::string origin = data.child("origin").text().get(); std::string origin = data.child("origin").text().get();
bool useAlpha = data.child("useAlpha");
bool tiled = data.child("tiled"); bool tiled = data.child("tiled");
//split position and dimension information //split position and dimension information
@ -127,7 +126,7 @@ GuiComponent* GuiTheme::createElement(pugi::xml_node data, GuiComponent* parent)
std::string originX, originY; std::string originX, originY;
splitString(origin, ' ', &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 //resolve to pixels from percentages/variables
int x = resolveExp(posX) * Renderer::getScreenWidth(); 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); GuiImage* comp = new GuiImage(x, y, "", w, h, true);
comp->setOrigin(ox, oy); comp->setOrigin(ox, oy);
comp->setAlpha(useAlpha);
comp->setTiling(tiled); comp->setTiling(tiled);
comp->setImage(path); comp->setImage(path);

View file

@ -5,6 +5,7 @@
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include "components/GuiInputConfig.h" #include "components/GuiInputConfig.h"
#include <SDL.h> #include <SDL.h>
#include <bcm_host.h>
bool PARSEGAMELISTONLY = false; bool PARSEGAMELISTONLY = false;
bool IGNOREGAMELIST = false; bool IGNOREGAMELIST = false;
@ -17,6 +18,8 @@ namespace fs = boost::filesystem;
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
bcm_host_init();
bool running = true; bool running = true;
//by the way, if anyone ever tries to port this to a different renderer but leave SDL as input - //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"; std::cout << "EmulationStation cleanly shutting down...\n";
SDL_Quit(); SDL_Quit();
bcm_host_deinit();
return 0; return 0;
} }