mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 14:15:38 +00:00
New renderer starting to work.
Image loading still not working and font sizing is still off. Resolution is hardcoded.
This commit is contained in:
parent
bff542f076
commit
0314a14849
6
Makefile
6
Makefile
|
@ -1,7 +1,7 @@
|
|||
CC=g++
|
||||
CFLAGS=-c -Wall
|
||||
LDFLAGS=-lSDL -lSDL_ttf -lSDL_image -lSDL_gfx -lboost_system -lboost_filesystem
|
||||
SRCSOURCES=main.cpp Renderer.cpp Renderer_draw.cpp GuiComponent.cpp InputManager.cpp SystemData.cpp GameData.cpp FolderData.cpp XMLReader.cpp MathExp.cpp components/GuiGameList.cpp components/GuiInputConfig.cpp components/GuiImage.cpp components/GuiMenu.cpp components/GuiTheme.cpp pugiXML/pugixml.cpp
|
||||
CFLAGS=-c -Wall -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I/usr/include/freetype2 -I/usr/include/SDL -I/usr/include
|
||||
LDFLAGS=-L/opt/vc/lib -lbcm_host -lEGL -lGLESv2 -lfreetype -lSDL -lboost_system -lboost_filesystem -lfreeimage
|
||||
SRCSOURCES=main.cpp Renderer.cpp Renderer_init_rpi.cpp Font.cpp Renderer_draw_gl.cpp GuiComponent.cpp InputManager.cpp SystemData.cpp GameData.cpp FolderData.cpp XMLReader.cpp MathExp.cpp components/GuiGameList.cpp components/GuiInputConfig.cpp components/GuiImage.cpp components/GuiMenu.cpp components/GuiTheme.cpp pugiXML/pugixml.cpp
|
||||
SOURCES=$(addprefix src/,$(SRCSOURCES))
|
||||
OBJECTS=$(SOURCES:.cpp=.o)
|
||||
EXECUTABLE=emulationstation
|
||||
|
|
257
src/Font.cpp
Normal file
257
src/Font.cpp
Normal file
|
@ -0,0 +1,257 @@
|
|||
#include "Font.h"
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include "Renderer.h"
|
||||
|
||||
FT_Library Font::sLibrary;
|
||||
|
||||
int Font::getDpiX() { return 300; }
|
||||
int Font::getDpiY() { return 300; }
|
||||
|
||||
void Font::initLibrary()
|
||||
{
|
||||
if(FT_Init_FreeType(&sLibrary))
|
||||
{
|
||||
std::cout << "Error initializing FreeType!\n";
|
||||
}
|
||||
}
|
||||
|
||||
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";
|
||||
while(true);
|
||||
}
|
||||
|
||||
FT_Set_Char_Size(face, 0, size * 64, getDpiX(), getDpiY());
|
||||
|
||||
buildAtlas();
|
||||
}
|
||||
|
||||
void Font::buildAtlas()
|
||||
{
|
||||
//find the size we should use
|
||||
FT_GlyphSlot g = face->glyph;
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
|
||||
/*for(int i = 32; i < 128; i++)
|
||||
{
|
||||
if(FT_Load_Char(face, i, FT_LOAD_RENDER))
|
||||
{
|
||||
fprintf(stderr, "Loading character %c failed!\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
w += g->bitmap.width;
|
||||
h = std::max(h, g->bitmap.rows);
|
||||
}*/
|
||||
|
||||
//GLES requires a power of two
|
||||
//the max size (GL_MAX_TEXTURE_SIZE) is pretty small too, like 3300, so just force it
|
||||
w = 2048;
|
||||
h = 2048;
|
||||
|
||||
textureWidth = w;
|
||||
textureHeight = h;
|
||||
|
||||
|
||||
|
||||
//create the texture
|
||||
glGenTextures(1, &textureID);
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
//copy the glyphs into the texture
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int maxHeight = 0;
|
||||
for(int i = 32; i < 128; i++)
|
||||
{
|
||||
if(FT_Load_Char(face, i, FT_LOAD_RENDER))
|
||||
continue;
|
||||
|
||||
//prints rendered texture to the console
|
||||
/*std::cout << "uploading at x: " << x << ", w: " << g->bitmap.width << " h: " << g->bitmap.rows << "\n";
|
||||
|
||||
for(int k = 0; k < g->bitmap.rows; k++)
|
||||
{
|
||||
for(int j = 0; j < g->bitmap.width; j++)
|
||||
{
|
||||
if(g->bitmap.buffer[g->bitmap.width * k + j])
|
||||
std::cout << ".";
|
||||
else
|
||||
std::cout << " ";
|
||||
}
|
||||
std::cout << "\n";
|
||||
}*/
|
||||
|
||||
if(x + g->bitmap.width >= textureWidth)
|
||||
{
|
||||
x = 0;
|
||||
y += maxHeight;
|
||||
maxHeight = 0;
|
||||
}
|
||||
|
||||
if(g->bitmap.rows > maxHeight)
|
||||
maxHeight = g->bitmap.rows;
|
||||
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x, 0, g->bitmap.width, g->bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
|
||||
|
||||
|
||||
charData[i].texX = x;
|
||||
charData[i].texY = 0;
|
||||
charData[i].texW = g->bitmap.width;
|
||||
charData[i].texH = g->bitmap.rows;
|
||||
charData[i].advX = g->metrics.horiAdvance >> 6;
|
||||
charData[i].advY = g->advance.y >> 6;
|
||||
charData[i].bearingY = g->metrics.horiBearingY >> 6;
|
||||
|
||||
x += g->bitmap.width;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Font::~Font()
|
||||
{
|
||||
FT_Done_Face(face);
|
||||
|
||||
glDeleteTextures(1, &textureID);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//why these aren't in an array:
|
||||
//openGL reads these in the order they are in memory
|
||||
//if I use an array, it will be 4 x values then 4 y values
|
||||
//it'll read XX, XX, YY instead of XY, XY, XY
|
||||
struct point {
|
||||
GLfloat pos0x;
|
||||
GLfloat pos0y;
|
||||
|
||||
GLfloat pos1x;
|
||||
GLfloat pos1y;
|
||||
|
||||
GLfloat pos2x;
|
||||
GLfloat pos2y;
|
||||
};
|
||||
|
||||
struct tex {
|
||||
GLfloat tex0x;
|
||||
GLfloat tex0y;
|
||||
|
||||
GLfloat tex1x;
|
||||
GLfloat tex1y;
|
||||
|
||||
GLfloat tex2x;
|
||||
GLfloat tex2y;
|
||||
};
|
||||
|
||||
void Font::drawText(std::string text, int startx, int starty, int color)
|
||||
{
|
||||
|
||||
starty += (face->height / face->units_per_EM) << 6; //(face->height / face->units_per_EM) << 6;
|
||||
|
||||
int pointCount = text.length() * 2;
|
||||
point* points = new point[pointCount];
|
||||
tex* texs = new tex[pointCount];
|
||||
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
|
||||
//texture atlas width/height
|
||||
float tw = (float)textureWidth;
|
||||
float th = (float)textureHeight;
|
||||
|
||||
int p = 0;
|
||||
int i = 0;
|
||||
|
||||
float x = startx;
|
||||
float y = starty;
|
||||
for(; p < pointCount; i++, p++)
|
||||
{
|
||||
int letter = text[i];
|
||||
|
||||
if(letter < 32 || letter >= 128)
|
||||
continue;
|
||||
|
||||
points[p].pos0x = x; points[p].pos0y = y + charData[letter].texH - charData[letter].bearingY;
|
||||
points[p].pos1x = x + charData[letter].texW; points[p].pos1y = y - charData[letter].bearingY;
|
||||
points[p].pos2x = x; points[p].pos2y = y - charData[letter].bearingY;
|
||||
|
||||
texs[p].tex0x = charData[letter].texX / tw; texs[p].tex0y = (charData[letter].texY + charData[letter].texH) / th;
|
||||
texs[p].tex1x = (charData[letter].texX + charData[letter].texW) / tw; texs[p].tex1y = charData[letter].texY / th;
|
||||
texs[p].tex2x = charData[letter].texX / tw; texs[p].tex2y = charData[letter].texY / th;
|
||||
|
||||
|
||||
p++;
|
||||
|
||||
points[p].pos0x = x; points[p].pos0y = y + charData[letter].texH - charData[letter].bearingY;
|
||||
points[p].pos1x = x + charData[letter].texW; points[p].pos1y = y - charData[letter].bearingY;
|
||||
points[p].pos2x = x + charData[letter].texW; points[p].pos2y = y + charData[letter].texH - charData[letter].bearingY;
|
||||
|
||||
texs[p].tex0x = charData[letter].texX / tw; texs[p].tex0y = (charData[letter].texY + charData[letter].texH) / th;
|
||||
texs[p].tex1x = (charData[letter].texX + charData[letter].texW) / tw; texs[p].tex1y = charData[letter].texY / th;
|
||||
texs[p].tex2x = texs[p].tex1x; texs[p].tex2y = texs[p].tex0y;
|
||||
|
||||
|
||||
x += charData[letter].advX;
|
||||
}
|
||||
|
||||
GLubyte* colors = new GLubyte[pointCount * 3 * 4];
|
||||
Renderer::buildGLColorArray(colors, color, pointCount * 3);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, points);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, texs);
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, pointCount * 3);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
//not sure if this properly deletes or not
|
||||
delete[] points;
|
||||
}
|
||||
|
||||
void Font::sizeText(std::string text, int* w, int* h)
|
||||
{
|
||||
if(w != NULL)
|
||||
{
|
||||
int cwidth = 0;
|
||||
for(unsigned int i = 0; i < text.length(); i++)
|
||||
{
|
||||
cwidth += charData[(int)text[i]].advX;
|
||||
}
|
||||
|
||||
*w = cwidth;
|
||||
}
|
||||
|
||||
if(h != NULL)
|
||||
*h = (face->height / face->units_per_EM) << 6;
|
||||
}
|
51
src/Font.h
Normal file
51
src/Font.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
//A truetype font loader and renderer, using FreeType 2 and OpenGL.
|
||||
|
||||
#ifndef _FONT_H_
|
||||
#define _FONT_H_
|
||||
|
||||
#include <string>
|
||||
#include <GLES/gl.h>
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
class Font
|
||||
{
|
||||
public:
|
||||
static void initLibrary();
|
||||
|
||||
Font(std::string path, int size);
|
||||
~Font();
|
||||
|
||||
FT_Face face;
|
||||
|
||||
struct charPosData {
|
||||
int texX;
|
||||
int texY;
|
||||
int texW;
|
||||
int texH;
|
||||
|
||||
int advX;
|
||||
int advY;
|
||||
|
||||
int bearingY;
|
||||
};
|
||||
|
||||
charPosData charData[128];
|
||||
|
||||
GLuint textureID;
|
||||
|
||||
void drawText(std::string text, int startx, int starty, int color);
|
||||
void sizeText(std::string text, int* w, int* h);
|
||||
private:
|
||||
|
||||
static int getDpiX();
|
||||
static int getDpiY();
|
||||
static FT_Library sLibrary;
|
||||
|
||||
void buildAtlas();
|
||||
|
||||
int textureWidth;
|
||||
int textureHeight;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -3,9 +3,6 @@
|
|||
|
||||
std::vector<GuiComponent*> renderVector;
|
||||
|
||||
unsigned int Renderer::getScreenWidth() { return Renderer::screen ? Renderer::screen->w : 640; } //1024; }
|
||||
unsigned int Renderer::getScreenHeight() { return Renderer::screen ? Renderer::screen->h : 480; }
|
||||
|
||||
void Renderer::registerComponent(GuiComponent* comp)
|
||||
{
|
||||
renderVector.push_back(comp);
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#ifndef _RENDERER_H_
|
||||
#define _RENDERER_H_
|
||||
|
||||
#define LAYER_COUNT 3
|
||||
|
||||
#define BIT(x) (1 << (x))
|
||||
|
||||
#include <vector>
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_ttf.h>
|
||||
#include <string>
|
||||
#include "Font.h"
|
||||
|
||||
class GuiComponent;
|
||||
|
||||
|
@ -18,22 +13,20 @@ namespace Renderer
|
|||
void unregisterComponent(GuiComponent* comp);
|
||||
void deleteAll();
|
||||
|
||||
void render();
|
||||
bool init(int w, int h);
|
||||
void deinit();
|
||||
|
||||
extern SDL_Surface* screen;
|
||||
extern TTF_Font* font;
|
||||
void render();
|
||||
|
||||
unsigned int getScreenWidth();
|
||||
unsigned int getScreenHeight();
|
||||
|
||||
enum FontSize { SMALL, MEDIUM, LARGE };
|
||||
bool loadFonts();
|
||||
extern bool loadedFonts;
|
||||
extern TTF_Font* fonts[3]; //should be FontSize size but I don't remember the syntax
|
||||
extern int fontHeight[3]; //same
|
||||
int getFontHeight(FontSize size); //sometimes font size is needed before fonts have been loaded; this takes care of that
|
||||
void buildGLColorArray(GLubyte* ptr, int color, unsigned int vertCount);
|
||||
|
||||
//drawing commands
|
||||
void swapBuffers();
|
||||
void drawRect(int x, int y, int w, int h, int color);
|
||||
void drawText(std::string text, int x, int y, int color, FontSize fontsize = MEDIUM);
|
||||
void drawCenteredText(std::string text, int xOffset, int y, int color, FontSize fontsize = MEDIUM);
|
||||
|
|
|
@ -1,188 +0,0 @@
|
|||
#include "Renderer.h"
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_ttf.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
SDL_Surface* Renderer::screen;
|
||||
bool Renderer::loadedFonts = false;
|
||||
TTF_Font* Renderer::fonts[3];
|
||||
int Renderer::fontHeight[3];
|
||||
|
||||
|
||||
//a utility function to convert an int (usually defined as hex) to the SDL color struct
|
||||
SDL_Color getSDLColor(int& int_color)
|
||||
{
|
||||
//taken off a forum post
|
||||
//#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
SDL_Color ret={(int_color & 0x00ff0000)/0x10000,(int_color & 0x0000ff00)/0x100,(int_color & 0x000000ff),0};
|
||||
//#else
|
||||
// SDL_Color ret={(int_color & 0x000000ff),(int_color & 0x0000ff00)/0x100,(int_color & 0x00ff0000)/0x10000,0};
|
||||
//#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Renderer::drawRect(int x, int y, int h, int w, int color)
|
||||
{
|
||||
SDL_Rect rect = {x, y, h, w};
|
||||
|
||||
//this is really dumb - FillRect takes a uint32, everything else uses getSDLColor
|
||||
//the internal ints that we use (e.g. 0x999999) are rendered wrong
|
||||
//i'm really bad at bitshifting so I don't know how to do this in a more efficient way
|
||||
SDL_Color conv = getSDLColor(color);
|
||||
color = SDL_MapRGB(Renderer::screen->format, conv.r, conv.g, conv.b);
|
||||
|
||||
SDL_FillRect(Renderer::screen, &rect, color);
|
||||
}
|
||||
|
||||
bool Renderer::loadFonts()
|
||||
{
|
||||
std::string fontPath = "LinLibertine_R.ttf";
|
||||
|
||||
//if our font isn't foud, make a last-ditch effort to load a system font
|
||||
if(!boost::filesystem::exists(fontPath))
|
||||
{
|
||||
std::cerr << "Error - " << fontPath << " font not found. Falling back to ";
|
||||
fontPath = "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf";
|
||||
std::cerr << fontPath << " (which may not exist).\n";
|
||||
}
|
||||
|
||||
int sizeArray[] = {Renderer::getScreenWidth() * 0.015, Renderer::getScreenWidth() * 0.03, Renderer::getScreenWidth() * 0.062};
|
||||
|
||||
|
||||
//the three here should be the font count but, again, I don't remember the syntax
|
||||
for(unsigned int i = 0; i < 3; i++)
|
||||
{
|
||||
TTF_Font* font = TTF_OpenFont(fontPath.c_str(), sizeArray[i]);
|
||||
if(!font)
|
||||
{
|
||||
std::cerr << "Error - could not load font!\n";
|
||||
std::cerr << TTF_GetError() << "\n";
|
||||
return false;
|
||||
}
|
||||
fonts[i] = font;
|
||||
TTF_SizeText(font, "HEIGHT", NULL, &fontHeight[i]); //gets the height of the string "HEIGHT" in this font (in pixels)
|
||||
}
|
||||
|
||||
loadedFonts = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
int Renderer::getFontHeight(FontSize size)
|
||||
{
|
||||
if(!loadedFonts)
|
||||
loadFonts();
|
||||
|
||||
return fontHeight[size];
|
||||
}
|
||||
|
||||
void Renderer::drawText(std::string text, int x, int y, int color, FontSize fontsize)
|
||||
{
|
||||
if(!loadedFonts)
|
||||
loadFonts();
|
||||
|
||||
TTF_Font* font = fonts[fontsize];
|
||||
|
||||
//SDL_Color is a struct of four bytes, with the first three being colors. An int is four bytes.
|
||||
//So, we can just pretend the int is an SDL_Color.
|
||||
//SDL_Color* sdlcolor = (SDL_Color*)&color;
|
||||
SDL_Color sdlcolor = getSDLColor(color);
|
||||
|
||||
SDL_Surface* textSurf = TTF_RenderText_Blended(font, text.c_str(), sdlcolor);
|
||||
if(textSurf == NULL)
|
||||
{
|
||||
std::cerr << "Error - could not render text \"" << text << "\" to surface!\n";
|
||||
std::cerr << TTF_GetError() << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Rect dest = {x, y};
|
||||
SDL_BlitSurface(textSurf, NULL, screen, &dest);
|
||||
SDL_FreeSurface(textSurf);
|
||||
}
|
||||
|
||||
void Renderer::drawCenteredText(std::string text, int xOffset, int y, int color, FontSize fontsize)
|
||||
{
|
||||
if(!loadedFonts)
|
||||
loadFonts();
|
||||
|
||||
TTF_Font* font = fonts[fontsize];
|
||||
|
||||
int w, h;
|
||||
TTF_SizeText(font, text.c_str(), &w, &h);
|
||||
|
||||
int x = (int)getScreenWidth() - w;
|
||||
x *= 0.5;
|
||||
|
||||
x += xOffset * 0.5;
|
||||
|
||||
drawText(text, x, y, color, fontsize);
|
||||
}
|
||||
|
||||
//this could probably be optimized
|
||||
//draws text and ensures it's never longer than xLen
|
||||
void Renderer::drawWrappedText(std::string text, int xStart, int yStart, int xLen, int color, FontSize fontsize)
|
||||
{
|
||||
if(!loadedFonts)
|
||||
loadFonts();
|
||||
|
||||
TTF_Font* font = fonts[fontsize];
|
||||
|
||||
int y = yStart;
|
||||
|
||||
std::string line, word, temp;
|
||||
int w, h;
|
||||
size_t space, newline;
|
||||
|
||||
while(text.length() > 0 || !line.empty()) //while there's text or we still have text to render
|
||||
{
|
||||
space = text.find(' ', 0);
|
||||
if(space == std::string::npos)
|
||||
space = text.length() - 1;
|
||||
|
||||
|
||||
word = text.substr(0, space + 1);
|
||||
|
||||
//check if the next word contains a newline
|
||||
newline = word.find('\n', 0);
|
||||
if(newline != std::string::npos)
|
||||
{
|
||||
word = word.substr(0, newline);
|
||||
text.erase(0, newline + 1);
|
||||
}else{
|
||||
text.erase(0, space + 1);
|
||||
}
|
||||
|
||||
temp = line + word;
|
||||
|
||||
TTF_SizeText(font, temp.c_str(), &w, &h);
|
||||
|
||||
//if we're on the last word and it'll fit on the line, just add it to the line
|
||||
if((w <= xLen && text.length() == 0) || newline != std::string::npos)
|
||||
{
|
||||
line = temp;
|
||||
word = "";
|
||||
}
|
||||
|
||||
|
||||
//if the next line will be too long or we're on the last of the text, render it
|
||||
if(w > xLen || text.length() == 0 || newline != std::string::npos)
|
||||
{
|
||||
//render line now
|
||||
if(w > 0) //make sure it's not blank
|
||||
drawText(line, xStart, y, color, fontsize);
|
||||
|
||||
//increment y by height and some extra padding for the next line
|
||||
y += h + 4;
|
||||
|
||||
//move the word we skipped to the next line
|
||||
line = word;
|
||||
}else{
|
||||
//there's still space, continue building the line
|
||||
line = temp;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
188
src/Renderer_draw_gl.cpp
Normal file
188
src/Renderer_draw_gl.cpp
Normal file
|
@ -0,0 +1,188 @@
|
|||
#include "Renderer.h"
|
||||
#include <GLES/gl.h>
|
||||
#include <iostream>
|
||||
#include "Font.h"
|
||||
|
||||
namespace Renderer {
|
||||
bool loadedFonts = false;
|
||||
|
||||
unsigned int getScreenWidth() { return 1680; }
|
||||
unsigned int getScreenHeight() { return 1050; }
|
||||
|
||||
void setColor4bArray(GLubyte* array, int color)
|
||||
{
|
||||
array[0] = (color & 0x00ff0000) / 0x10000;
|
||||
array[1] = (color & 0x0000ff00) / 0x100;
|
||||
array[2] = (color & 0x000000ff);
|
||||
array[3] = 255;
|
||||
}
|
||||
|
||||
void buildGLColorArray(GLubyte* ptr, int color, unsigned int vertCount)
|
||||
{
|
||||
for(unsigned int i = 0; i < vertCount; i++)
|
||||
{
|
||||
setColor4bArray(ptr, color);
|
||||
ptr += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void drawRect(int x, int y, int w, int h, int color)
|
||||
{
|
||||
GLfloat points[12];
|
||||
|
||||
points[0] = x; points [1] = y;
|
||||
points[2] = x; points[3] = y + h;
|
||||
points[4] = x + w; points[5] = y;
|
||||
|
||||
points[6] = x + w; points[7] = y;
|
||||
points[8] = x; points[9] = y + h;
|
||||
points[10] = x + w; points[11] = y + h;
|
||||
|
||||
GLubyte colors[6*4];
|
||||
buildGLColorArray(colors, color, 6);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, points);
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
Font* defaultFont = NULL;
|
||||
void loadFonts()
|
||||
{
|
||||
std::cout << "loading fonts\n";
|
||||
|
||||
if(defaultFont != NULL)
|
||||
delete defaultFont;
|
||||
|
||||
defaultFont = new Font("LinLibertine_R.ttf", 12);
|
||||
|
||||
loadedFonts = true;
|
||||
}
|
||||
|
||||
void unloadFonts()
|
||||
{
|
||||
if(defaultFont)
|
||||
{
|
||||
delete defaultFont;
|
||||
defaultFont = NULL;
|
||||
}
|
||||
|
||||
loadedFonts = false;
|
||||
}
|
||||
|
||||
Font* getFont(FontSize size)
|
||||
{
|
||||
return defaultFont;
|
||||
}
|
||||
|
||||
|
||||
int getFontHeight(FontSize size)
|
||||
{
|
||||
if(!loadedFonts)
|
||||
loadFonts();
|
||||
|
||||
int h;
|
||||
getFont(size)->sizeText("", NULL, &h);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
void drawText(std::string text, int x, int y, int color, FontSize font)
|
||||
{
|
||||
if(!loadedFonts)
|
||||
loadFonts();
|
||||
|
||||
getFont(font)->drawText(text, x, y, color);
|
||||
}
|
||||
|
||||
void drawCenteredText(std::string text, int xOffset, int y, int color, FontSize fontsize)
|
||||
{
|
||||
if(!loadedFonts)
|
||||
loadFonts();
|
||||
|
||||
Font* font = getFont(fontsize);
|
||||
|
||||
int w, h;
|
||||
font->sizeText(text, &w, &h);
|
||||
|
||||
int x = (int)getScreenWidth() - w;
|
||||
x *= 0.5;
|
||||
|
||||
x += xOffset * 0.5;
|
||||
|
||||
drawText(text, x, y, color, fontsize);
|
||||
}
|
||||
|
||||
//this could probably be optimized
|
||||
//draws text and ensures it's never longer than xLen
|
||||
void drawWrappedText(std::string text, int xStart, int yStart, int xLen, int color, FontSize fontsize)
|
||||
{
|
||||
if(!loadedFonts)
|
||||
loadFonts();
|
||||
|
||||
Font* font = getFont(fontsize);
|
||||
|
||||
int y = yStart;
|
||||
|
||||
std::string line, word, temp;
|
||||
int w, h;
|
||||
size_t space, newline;
|
||||
|
||||
while(text.length() > 0 || !line.empty()) //while there's text or we still have text to render
|
||||
{
|
||||
space = text.find(' ', 0);
|
||||
if(space == std::string::npos)
|
||||
space = text.length() - 1;
|
||||
|
||||
|
||||
word = text.substr(0, space + 1);
|
||||
|
||||
//check if the next word contains a newline
|
||||
newline = word.find('\n', 0);
|
||||
if(newline != std::string::npos)
|
||||
{
|
||||
word = word.substr(0, newline);
|
||||
text.erase(0, newline + 1);
|
||||
}else{
|
||||
text.erase(0, space + 1);
|
||||
}
|
||||
|
||||
temp = line + word;
|
||||
|
||||
font->sizeText(temp, &w, &h);
|
||||
|
||||
//if we're on the last word and it'll fit on the line, just add it to the line
|
||||
if((w <= xLen && text.length() == 0) || newline != std::string::npos)
|
||||
{
|
||||
line = temp;
|
||||
word = "";
|
||||
}
|
||||
|
||||
|
||||
//if the next line will be too long or we're on the last of the text, render it
|
||||
if(w > xLen || text.length() == 0 || newline != std::string::npos)
|
||||
{
|
||||
//render line now
|
||||
if(w > 0) //make sure it's not blank
|
||||
drawText(line, xStart, y, color, fontsize);
|
||||
|
||||
//increment y by height and some extra padding for the next line
|
||||
y += h + 4;
|
||||
|
||||
//move the word we skipped to the next line
|
||||
line = word;
|
||||
}else{
|
||||
//there's still space, continue building the line
|
||||
line = temp;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
};
|
178
src/Renderer_init_rpi.cpp
Normal file
178
src/Renderer_init_rpi.cpp
Normal file
|
@ -0,0 +1,178 @@
|
|||
#include <bcm_host.h>
|
||||
#include <iostream>
|
||||
#include <bcm_host.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include "Font.h"
|
||||
|
||||
namespace Renderer
|
||||
{
|
||||
EGLDisplay display;
|
||||
EGLSurface surface;
|
||||
EGLContext context;
|
||||
EGLConfig config;
|
||||
|
||||
static EGL_DISPMANX_WINDOW_T nativewindow;
|
||||
|
||||
bool createSurface()
|
||||
{
|
||||
std::cout << "Creating surface...\n";
|
||||
|
||||
|
||||
DISPMANX_ELEMENT_HANDLE_T dispman_element;
|
||||
DISPMANX_DISPLAY_HANDLE_T dispman_display;
|
||||
DISPMANX_UPDATE_HANDLE_T dispman_update;
|
||||
VC_RECT_T dst_rect;
|
||||
VC_RECT_T src_rect;
|
||||
|
||||
|
||||
|
||||
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if(display == EGL_NO_DISPLAY)
|
||||
{
|
||||
std::cerr << "Error getting display!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = eglInitialize(display, NULL, NULL);
|
||||
if(result == EGL_FALSE)
|
||||
{
|
||||
std::cerr << "Error initializing display!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
result = eglBindAPI(EGL_OPENGL_ES_API);
|
||||
if(result == EGL_FALSE)
|
||||
{
|
||||
std::cerr << "Error binding API!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static const EGLint config_attributes[] =
|
||||
{
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_ALPHA_SIZE, 8,
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
GLint numConfigs;
|
||||
result = eglChooseConfig(display, config_attributes, &config, 1, &numConfigs);
|
||||
|
||||
if(result == EGL_FALSE)
|
||||
{
|
||||
std::cerr << "Error choosing config!\n";
|
||||
return false;
|
||||
}
|
||||
std::cout << "numConfigs: " << numConfigs << "\n";
|
||||
|
||||
|
||||
context = eglCreateContext(display, config, EGL_NO_CONTEXT, NULL);
|
||||
if(context == EGL_NO_CONTEXT)
|
||||
{
|
||||
std::cout << "Error: " << eglGetError() << "\n";
|
||||
|
||||
std::cerr << "Error getting context!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
unsigned int display_width;
|
||||
unsigned int display_height;
|
||||
|
||||
bool success = graphics_get_display_size(0, &display_width, &display_height); //0 = LCD
|
||||
|
||||
if(success < 0)
|
||||
{
|
||||
std::cerr << "Error getting display size!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << "Display size is " << display_width << "x" << display_height << "\n";
|
||||
|
||||
|
||||
dst_rect.x = 0; dst_rect.y = 0;
|
||||
dst_rect.width = display_width; dst_rect.height = display_height;
|
||||
|
||||
src_rect.x = 0; src_rect.y = 0;
|
||||
src_rect.width = display_width << 16; src_rect.height = display_height << 16;
|
||||
|
||||
dispman_display = vc_dispmanx_display_open(0); //0 = LCD
|
||||
dispman_update = vc_dispmanx_update_start(0);
|
||||
|
||||
dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display, 0 /*layer*/, &dst_rect, 0 /*src*/, &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0 /*clamp*/, DISPMANX_NO_ROTATE /*transform*/);
|
||||
|
||||
nativewindow.element = dispman_element;
|
||||
nativewindow.width = display_width; nativewindow.height = display_height;
|
||||
vc_dispmanx_update_submit_sync(dispman_update);
|
||||
|
||||
|
||||
|
||||
|
||||
surface = eglCreateWindowSurface(display, config, &nativewindow, NULL);
|
||||
if(surface == EGL_NO_SURFACE)
|
||||
{
|
||||
std::cerr << "Error creating window surface!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
result = eglMakeCurrent(display, surface, surface, context);
|
||||
if(result == EGL_FALSE)
|
||||
{
|
||||
std::cerr << "Error with eglMakeCurrent!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::cout << "success!\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void swapBuffers()
|
||||
{
|
||||
eglSwapBuffers(display, surface);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void destroySurface()
|
||||
{
|
||||
eglSwapBuffers(display, surface);
|
||||
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglDestroySurface(display, surface);
|
||||
eglDestroyContext(display, context);
|
||||
eglTerminate(display);
|
||||
}
|
||||
|
||||
bool init(int w, int h)
|
||||
{
|
||||
bcm_host_init();
|
||||
bool surface = createSurface();
|
||||
|
||||
if(!surface)
|
||||
return false;
|
||||
|
||||
Font::initLibrary();
|
||||
|
||||
glViewport(0, 0, 1680, 1050);
|
||||
glOrthof(0, 1680, 1050, 0, -1.0, 1.0);
|
||||
glClearColor(0.5f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void unloadFonts();
|
||||
void deinit()
|
||||
{
|
||||
unloadFonts();
|
||||
destroySurface();
|
||||
bcm_host_deinit();
|
||||
}
|
||||
};
|
|
@ -5,6 +5,7 @@
|
|||
#include <fstream>
|
||||
#include <stdlib.h>
|
||||
#include <SDL/SDL_joystick.h>
|
||||
#include "Renderer.h"
|
||||
|
||||
std::vector<SystemData*> SystemData::sSystemVector;
|
||||
|
||||
|
@ -70,6 +71,8 @@ void SystemData::launchGame(GameData* game)
|
|||
//suspend SDL joystick events (these'll pile up even while something else is running)
|
||||
SDL_JoystickEventState(0);
|
||||
|
||||
Renderer::deinit();
|
||||
|
||||
std::string command = mLaunchCommand;
|
||||
|
||||
command = strreplace(command, "%ROM%", game->getBashPath());
|
||||
|
@ -81,6 +84,8 @@ void SystemData::launchGame(GameData* game)
|
|||
|
||||
std::cout << "...launch terminated!\n";
|
||||
|
||||
Renderer::init(0, 0);
|
||||
|
||||
//re-enable SDL joystick events
|
||||
SDL_JoystickEventState(1);
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
#include "GuiMenu.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
//#define DRAWFRAMERATE
|
||||
|
||||
#ifdef DRAWFRAMERATE
|
||||
#include <sstream>
|
||||
extern float FRAMERATE;
|
||||
|
@ -88,7 +86,7 @@ void GuiGameList::setSystemId(int id)
|
|||
|
||||
void GuiGameList::onRender()
|
||||
{
|
||||
Renderer::drawRect(0, 0, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0xFFFFFF);
|
||||
//Renderer::drawRect(0, 0, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0xFFFFFF);
|
||||
|
||||
if(mTheme)
|
||||
mTheme->render();
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include "../GameData.h"
|
||||
#include "../FolderData.h"
|
||||
|
||||
#define DRAWFRAMERATE
|
||||
|
||||
class GuiGameList : GuiComponent
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
#include "GuiImage.h"
|
||||
#include <SDL/SDL_image.h>
|
||||
#include <SDL/SDL_rotozoom.h>
|
||||
#include <iostream>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
int GuiImage::getWidth() { if(mSurface) return mSurface->w; else return 0; }
|
||||
int GuiImage::getHeight() { if(mSurface) return mSurface->h; else return 0; }
|
||||
int GuiImage::getWidth() { return mWidth; }
|
||||
int GuiImage::getHeight() { return 100; }
|
||||
|
||||
GuiImage::GuiImage(int offsetX, int offsetY, std::string path, unsigned int maxWidth, unsigned int maxHeight, bool resizeExact)
|
||||
{
|
||||
mSurface = NULL;
|
||||
mTextureID = 0;
|
||||
|
||||
mOffsetX = offsetX;
|
||||
mOffsetY = offsetY;
|
||||
|
@ -18,6 +16,9 @@ GuiImage::GuiImage(int offsetX, int offsetY, std::string path, unsigned int maxW
|
|||
mOriginX = 0.5;
|
||||
mOriginY = 0.5;
|
||||
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
|
||||
mTiled = false;
|
||||
|
||||
mMaxWidth = maxWidth;
|
||||
|
@ -32,92 +33,96 @@ GuiImage::GuiImage(int offsetX, int offsetY, std::string path, unsigned int maxW
|
|||
|
||||
GuiImage::~GuiImage()
|
||||
{
|
||||
if(mSurface)
|
||||
SDL_FreeSurface(mSurface);
|
||||
unloadImage();
|
||||
}
|
||||
|
||||
void GuiImage::loadImage(std::string path)
|
||||
{
|
||||
if(boost::filesystem::exists(path))
|
||||
//make sure the file *exists*
|
||||
if(!boost::filesystem::exists(path))
|
||||
{
|
||||
//start loading the image
|
||||
SDL_Surface* newSurf = IMG_Load(path.c_str());
|
||||
|
||||
//if we started loading something else or failed to load, don't bother resizing
|
||||
if(newSurf == NULL)
|
||||
{
|
||||
std::cerr << "Error loading image.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
resizeSurface(&newSurf);
|
||||
|
||||
//convert it into display format for faster rendering
|
||||
SDL_Surface* dispSurf;
|
||||
if(mUseAlpha)
|
||||
dispSurf = SDL_DisplayFormatAlpha(newSurf);
|
||||
else
|
||||
dispSurf = SDL_DisplayFormat(newSurf);
|
||||
|
||||
SDL_FreeSurface(newSurf);
|
||||
newSurf = dispSurf;
|
||||
|
||||
|
||||
//finally set the image and delete the old one
|
||||
if(mSurface)
|
||||
SDL_FreeSurface(mSurface);
|
||||
|
||||
mSurface = newSurf;
|
||||
|
||||
updateRect();
|
||||
|
||||
}else{
|
||||
std::cerr << "File \"" << path << "\" not found!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
FREE_IMAGE_FORMAT format = FIF_UNKNOWN;
|
||||
FIBITMAP* image = NULL;
|
||||
BYTE* imageData = NULL;
|
||||
unsigned int width, height;
|
||||
|
||||
//detect the filetype
|
||||
//format = FreeImage_GetFileType(path.c_str(), 0);
|
||||
if(format == FIF_UNKNOWN)
|
||||
format = FreeImage_GetFIFFromFilename(path.c_str());
|
||||
if(format == FIF_UNKNOWN)
|
||||
{
|
||||
std::cerr << "Error - could not detect filetype for image \"" << path << "\"!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
//make sure it loaded properly
|
||||
if(!image)
|
||||
{
|
||||
std::cerr << "Error loading image \"" << path << "\"!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
imageData = FreeImage_GetBits(image);
|
||||
if(!imageData)
|
||||
{
|
||||
std::cerr << "Error retriving bits from image \"" << path << "\"!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
width = FreeImage_GetWidth(image);
|
||||
height = FreeImage_GetHeight(image);
|
||||
|
||||
if(!width || !height)
|
||||
{
|
||||
std::cerr << "Width or height are zero for image \"" << path << "\"!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
//force power of two for testing
|
||||
width = 512; height = 512;
|
||||
|
||||
//now for the openGL texture stuff
|
||||
glGenTextures(1, &mTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, mTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
//free the image data
|
||||
FreeImage_Unload(image);
|
||||
|
||||
std::cout << "Image load successful, w: " << mWidth << " h: " << mHeight << " texID: " << mTextureID << "\n";
|
||||
}
|
||||
|
||||
//enjoy this overly-complicated pointer stuff that results from splitting a function too late
|
||||
void GuiImage::resizeSurface(SDL_Surface** surfRef)
|
||||
void GuiImage::unloadImage()
|
||||
{
|
||||
if(mTiled)
|
||||
return;
|
||||
|
||||
SDL_Surface* newSurf = *surfRef;
|
||||
if(mResizeExact)
|
||||
if(mTextureID)
|
||||
{
|
||||
double scaleX = (double)mMaxWidth / (double)newSurf->w;
|
||||
double scaleY = (double)mMaxHeight / (double)newSurf->h;
|
||||
std::cout << "deleting texture\n";
|
||||
glDeleteTextures(1, &mTextureID);
|
||||
|
||||
if(scaleX == 0)
|
||||
scaleX = scaleY;
|
||||
if(scaleY == 0)
|
||||
scaleY = scaleX;
|
||||
|
||||
SDL_Surface* resSurf = zoomSurface(newSurf, scaleX, scaleY, SMOOTHING_OFF);
|
||||
SDL_FreeSurface(newSurf);
|
||||
newSurf = resSurf;
|
||||
}else{
|
||||
if(mMaxWidth && newSurf->w > mMaxWidth)
|
||||
{
|
||||
double scale = (double)mMaxWidth / (double)newSurf->w;
|
||||
|
||||
SDL_Surface* resSurf = zoomSurface(newSurf, scale, scale, SMOOTHING_OFF);
|
||||
SDL_FreeSurface(newSurf);
|
||||
newSurf = resSurf;
|
||||
}
|
||||
|
||||
if(mMaxHeight && newSurf->h > mMaxHeight)
|
||||
{
|
||||
double scale = (double)mMaxHeight / (double)newSurf->h;
|
||||
|
||||
SDL_Surface* resSurf = zoomSurface(newSurf, scale, scale, SMOOTHING_OFF);
|
||||
SDL_FreeSurface(newSurf);
|
||||
newSurf = resSurf;
|
||||
}
|
||||
mTextureID = 0;
|
||||
}
|
||||
|
||||
*surfRef = newSurf;
|
||||
}
|
||||
|
||||
void GuiImage::setImage(std::string path)
|
||||
|
@ -127,32 +132,16 @@ void GuiImage::setImage(std::string path)
|
|||
|
||||
mPath = path;
|
||||
|
||||
if(mSurface)
|
||||
{
|
||||
SDL_FreeSurface(mSurface);
|
||||
mSurface = NULL;
|
||||
}
|
||||
|
||||
unloadImage();
|
||||
if(!path.empty())
|
||||
loadImage(path);
|
||||
|
||||
}
|
||||
|
||||
void GuiImage::updateRect()
|
||||
{
|
||||
mRect.x = mOffsetX /*- mSurface->w*/ - (mSurface->w * mOriginX);
|
||||
mRect.y = mOffsetY - (mSurface->h * mOriginY);
|
||||
mRect.w = mSurface->w;
|
||||
mRect.h = mSurface->h;
|
||||
}
|
||||
|
||||
void GuiImage::setOrigin(float originX, float originY)
|
||||
{
|
||||
mOriginX = originX;
|
||||
mOriginY = originY;
|
||||
|
||||
if(mSurface)
|
||||
updateRect();
|
||||
}
|
||||
|
||||
void GuiImage::setTiling(bool tile)
|
||||
|
@ -166,36 +155,51 @@ void GuiImage::setTiling(bool tile)
|
|||
void GuiImage::setAlpha(bool useAlpha)
|
||||
{
|
||||
mUseAlpha = useAlpha;
|
||||
|
||||
if(mSurface)
|
||||
{
|
||||
SDL_FreeSurface(mSurface);
|
||||
mSurface = NULL;
|
||||
loadImage(mPath);
|
||||
}
|
||||
}
|
||||
|
||||
bool dbg = false;
|
||||
|
||||
void GuiImage::onRender()
|
||||
{
|
||||
if(mSurface)
|
||||
if(mTextureID)
|
||||
{
|
||||
if(mTiled)
|
||||
{
|
||||
SDL_Rect rect = mRect;
|
||||
for(int x = 0; x < mMaxWidth / mSurface->w + 0.5; x++)
|
||||
{
|
||||
for(int y = 0; y < mMaxHeight / mSurface->h + 0.5; y++)
|
||||
{
|
||||
SDL_BlitSurface(mSurface, NULL, Renderer::screen, &rect);
|
||||
rect.y += mSurface->h;
|
||||
}
|
||||
rect.x += mSurface->w;
|
||||
rect.y = mRect.y;
|
||||
}
|
||||
}else{
|
||||
SDL_BlitSurface(mSurface, NULL, Renderer::screen, &mRect);
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, mTextureID);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
|
||||
GLfloat points[12];
|
||||
points[0] = mOffsetX - (mWidth * mOriginX); points[1] = mOffsetY - (mHeight * mOriginY);
|
||||
points[2] = mOffsetX - (mWidth * mOriginX); points[3] = mOffsetY + (mHeight * (1 - mOriginY));
|
||||
points[4] = mOffsetX + (mWidth * (1 - mOriginX)); points[5] = mOffsetY - (mHeight * mOriginY);
|
||||
|
||||
points[6] = mOffsetX + (mWidth * (1 - mOriginX)); points[7] = mOffsetY - (mHeight * mOriginY);
|
||||
points[8] = mOffsetX - (mWidth * mOriginX); points[9] = mOffsetY + (mHeight * (1 - mOriginY));
|
||||
points[10] = mOffsetX + (mWidth * (1 -mOriginX)); points[11] = mOffsetY + (mHeight * (1 - mOriginY));
|
||||
|
||||
//std::cout << "x: " << points[0] << " y: " << points[1] << " to x: " << points[10] << " y: " << points[11] << std::endl;
|
||||
//std::cout << "(w: " << mWidth << " h: " << mHeight << ")" << std::endl;
|
||||
|
||||
GLfloat texs[12];
|
||||
texs[0] = 0; texs[1] = 0;
|
||||
texs[2] = 0; texs[3] = 1;
|
||||
texs[4] = 1; texs[5] = 0;
|
||||
|
||||
texs[6] = 1; texs[7] = 0;
|
||||
texs[8] = 0; texs[9] = 1;
|
||||
texs[10] = 1; texs[11] = 1;
|
||||
|
||||
|
||||
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, points);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, texs);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
#define _GUIIMAGE_H_
|
||||
|
||||
#include "../GuiComponent.h"
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_thread.h>
|
||||
#include <string>
|
||||
#include <FreeImage.h>
|
||||
#include <GLES/gl.h>
|
||||
|
||||
class GuiImage : public GuiComponent
|
||||
{
|
||||
|
@ -28,14 +28,14 @@ private:
|
|||
bool mResizeExact, mTiled, mUseAlpha;
|
||||
|
||||
void loadImage(std::string path);
|
||||
void resizeSurface(SDL_Surface** surfRef);
|
||||
void updateRect();
|
||||
void unloadImage();
|
||||
|
||||
std::string mPath;
|
||||
|
||||
SDL_Surface* mSurface;
|
||||
int mOffsetX, mOffsetY;
|
||||
SDL_Rect mRect;
|
||||
unsigned int mWidth, mHeight;
|
||||
|
||||
GLuint mTextureID;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
29
src/main.cpp
29
src/main.cpp
|
@ -1,11 +1,10 @@
|
|||
#include <iostream>
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_ttf.h>
|
||||
#include "Renderer.h"
|
||||
#include "components/GuiGameList.h"
|
||||
#include "SystemData.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
#include "components/GuiInputConfig.h"
|
||||
#include <SDL.h>
|
||||
|
||||
bool PARSEGAMELISTONLY = false;
|
||||
bool IGNOREGAMELIST = false;
|
||||
|
@ -29,13 +28,9 @@ int main(int argc, char* argv[])
|
|||
std::cerr << "Are you in the 'video' and 'input' groups? Are you running with X closed?\n";
|
||||
return 1;
|
||||
}
|
||||
if(TTF_Init() != 0)
|
||||
{
|
||||
std::cerr << "Error - could not initialize SDL_ttf!\n";
|
||||
std::cerr << " " << TTF_GetError() << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_Surface* sdlScreen = SDL_SetVideoMode(1, 1, 0, SDL_SWSURFACE);
|
||||
std::cout << "Fake SDL window is " << sdlScreen->w << "x" << sdlScreen->h << "\n";
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
@ -61,21 +56,14 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
}
|
||||
|
||||
Renderer::screen = SDL_SetVideoMode(width, height, 16, SDL_SWSURFACE); //| SDL_FULLSCREEN);
|
||||
|
||||
if(Renderer::screen == NULL)
|
||||
if(!Renderer::init(width, height))
|
||||
{
|
||||
std::cerr << "Error - could not set video mode!\n";
|
||||
std::cerr << " " << SDL_GetError() << "\n";
|
||||
std::cerr << "\nYou may want to try using -w and -h to specify a resolution.\n";
|
||||
std::cerr << "Error initializing renderer!\n";
|
||||
return 1;
|
||||
}else{
|
||||
std::cout << "Video mode is " << Renderer::screen->w << "x" << Renderer::screen->h << "\n";
|
||||
}
|
||||
|
||||
SDL_ShowCursor(false);
|
||||
SDL_JoystickEventState(SDL_ENABLE);
|
||||
|
||||
SDL_JoystickEventState(SDL_ENABLE);
|
||||
|
||||
|
||||
//make sure the config directory exists
|
||||
|
@ -187,15 +175,16 @@ int main(int argc, char* argv[])
|
|||
GuiComponent::processTicks(deltaTime);
|
||||
|
||||
Renderer::render();
|
||||
SDL_Flip(Renderer::screen);
|
||||
Renderer::swapBuffers();
|
||||
}
|
||||
|
||||
|
||||
Renderer::deleteAll();
|
||||
Renderer::deinit();
|
||||
SystemData::deleteSystems();
|
||||
|
||||
std::cout << "EmulationStation cleanly shutting down...\n";
|
||||
|
||||
TTF_Quit();
|
||||
SDL_Quit();
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue