Redid the entire Renderer

Made all components render using triangle strips
This commit is contained in:
Tomas Jakobsson 2019-08-08 22:16:11 +02:00
parent ce8b16aacf
commit a02a747c50
49 changed files with 1046 additions and 876 deletions

View file

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 2.8) cmake_minimum_required(VERSION 2.8)
option(GLES "Set to ON if targeting OpenGL ES" ${GLES}) option(GLES "Set to ON if targeting Embedded OpenGL" ${GLES})
option(GL "Set to ON if targeting Desktop OpenGL" ${GL}) option(GL "Set to ON if targeting Desktop OpenGL" ${GL})
option(RPI "Set to ON to enable the Raspberry PI video player (omxplayer)" ${RPI}) option(RPI "Set to ON to enable the Raspberry PI video player (omxplayer)" ${RPI})
@ -16,7 +16,7 @@ LIST(APPEND CMAKE_MODULE_PATH
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
#set up OpenGL system variable #set up OpenGL system variable
if(GLES) if(GLES)
set(GLSystem "OpenGL ES" CACHE STRING "The OpenGL system to be used") set(GLSystem "Embedded OpenGL" CACHE STRING "The OpenGL system to be used")
elseif(GL) elseif(GL)
set(GLSystem "Desktop OpenGL" CACHE STRING "The OpenGL system to be used") set(GLSystem "Desktop OpenGL" CACHE STRING "The OpenGL system to be used")
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
@ -24,13 +24,13 @@ elseif(GL)
elseif(EXISTS "${CMAKE_FIND_ROOT_PATH}/opt/vc/include/bcm_host.h") elseif(EXISTS "${CMAKE_FIND_ROOT_PATH}/opt/vc/include/bcm_host.h")
MESSAGE("bcm_host.h found") MESSAGE("bcm_host.h found")
set(BCMHOST found) set(BCMHOST found)
set(GLSystem "OpenGL ES" CACHE STRING "The OpenGL system to be used") set(GLSystem "Embedded OpenGL" CACHE STRING "The OpenGL system to be used")
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
#check if we're running on OSMC Vero4K #check if we're running on OSMC Vero4K
elseif(EXISTS "${CMAKE_FIND_ROOT_PATH}/opt/vero3/lib/libMali.so") elseif(EXISTS "${CMAKE_FIND_ROOT_PATH}/opt/vero3/lib/libMali.so")
MESSAGE("libMali.so found") MESSAGE("libMali.so found")
set(VERO4K found) set(VERO4K found)
set(GLSystem "OpenGL ES" CACHE STRING "The OpenGL system to be used") set(GLSystem "Embedded OpenGL" CACHE STRING "The OpenGL system to be used")
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
#check if we're running on olinuxino / odroid / etc #check if we're running on olinuxino / odroid / etc
elseif(EXISTS "${CMAKE_FIND_ROOT_PATH}/usr/lib/libMali.so" OR elseif(EXISTS "${CMAKE_FIND_ROOT_PATH}/usr/lib/libMali.so" OR
@ -39,12 +39,12 @@ elseif(EXISTS "${CMAKE_FIND_ROOT_PATH}/usr/lib/libMali.so" OR
EXISTS "${CMAKE_FIND_ROOT_PATH}/usr/lib/arm-linux-gnueabihf/mali-egl/libmali.so" OR EXISTS "${CMAKE_FIND_ROOT_PATH}/usr/lib/arm-linux-gnueabihf/mali-egl/libmali.so" OR
EXISTS "${CMAKE_FIND_ROOT_PATH}/usr/lib/arm-linux-gnueabihf/libmali.so") EXISTS "${CMAKE_FIND_ROOT_PATH}/usr/lib/arm-linux-gnueabihf/libmali.so")
MESSAGE("libMali.so found") MESSAGE("libMali.so found")
set(GLSystem "OpenGL ES" CACHE STRING "The OpenGL system to be used") set(GLSystem "Embedded OpenGL" CACHE STRING "The OpenGL system to be used")
else() else()
set(GLSystem "Desktop OpenGL" CACHE STRING "The OpenGL system to be used") set(GLSystem "Desktop OpenGL" CACHE STRING "The OpenGL system to be used")
endif(GLES) endif(GLES)
set_property(CACHE GLSystem PROPERTY STRINGS "Desktop OpenGL" "OpenGL ES") set_property(CACHE GLSystem PROPERTY STRINGS "Desktop OpenGL" "Embedded OpenGL")
#finding necessary packages #finding necessary packages
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
@ -109,9 +109,9 @@ endif()
endif() endif()
if(${GLSystem} MATCHES "Desktop OpenGL") if(${GLSystem} MATCHES "Desktop OpenGL")
add_definitions(-DUSE_OPENGL_DESKTOP) add_definitions(-DUSE_OPENGL_21)
else() else()
add_definitions(-DUSE_OPENGL_ES) add_definitions(-DUSE_OPENGLES_10)
endif() endif()
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------

View file

@ -11,7 +11,6 @@
#include "FileFilterIndex.h" #include "FileFilterIndex.h"
#include "Log.h" #include "Log.h"
#include "PowerSaver.h" #include "PowerSaver.h"
#include "Renderer.h"
#include "Sound.h" #include "Sound.h"
#include "SystemData.h" #include "SystemData.h"
#include <unordered_map> #include <unordered_map>

View file

@ -1,7 +1,7 @@
#include "components/AsyncReqComponent.h" #include "components/AsyncReqComponent.h"
#include "renderers/Renderer.h"
#include "HttpReq.h" #include "HttpReq.h"
#include "Renderer.h"
AsyncReqComponent::AsyncReqComponent(Window* window, std::shared_ptr<HttpReq> req, std::function<void(std::shared_ptr<HttpReq>)> onSuccess, std::function<void()> onCancel) AsyncReqComponent::AsyncReqComponent(Window* window, std::shared_ptr<HttpReq> req, std::function<void(std::shared_ptr<HttpReq>)> onSuccess, std::function<void()> onCancel)
: GuiComponent(window), : GuiComponent(window),

View file

@ -1,7 +1,6 @@
#include "components/RatingComponent.h" #include "components/RatingComponent.h"
#include "resources/TextureResource.h" #include "resources/TextureResource.h"
#include "Renderer.h"
#include "ThemeData.h" #include "ThemeData.h"
RatingComponent::RatingComponent(Window* window) : GuiComponent(window), mColorShift(0xFFFFFFFF) RatingComponent::RatingComponent(Window* window) : GuiComponent(window), mColorShift(0xFFFFFFFF)
@ -77,37 +76,28 @@ void RatingComponent::onSizeChanged()
void RatingComponent::updateVertices() void RatingComponent::updateVertices()
{ {
const float numStars = NUM_RATING_STARS; const float numStars = NUM_RATING_STARS;
const float h = Math::round(getSize().y()); // is the same as a single star's width const float h = Math::round(getSize().y()); // is the same as a single star's width
const float w = Math::round(h * mValue * numStars); const float w = Math::round(h * mValue * numStars);
const float fw = Math::round(h * numStars); const float fw = Math::round(h * numStars);
const unsigned int color = Renderer::convertColor(mColorShift);
mVertices[0].pos = Vector2f(0.0f, 0.0f); mVertices[0] = { { 0.0f, 0.0f }, { 0.0f, 1.0f }, color };
mVertices[0].tex = Vector2f(0.0f, 1.0f); mVertices[1] = { { 0.0f, h }, { 0.0f, 0.0f }, color };
mVertices[1].pos = Vector2f(w, h); mVertices[2] = { { w, 0.0f }, { mValue * numStars, 1.0f }, color };
mVertices[1].tex = Vector2f(mValue * numStars, 0.0f); mVertices[3] = { { w, h }, { mValue * numStars, 0.0f }, color };
mVertices[2].pos = Vector2f(0.0f, h);
mVertices[2].tex = Vector2f(0.0f, 0.0f);
mVertices[3] = mVertices[0]; mVertices[4] = { { 0.0f, 0.0f }, { 0.0f, 1.0f }, color };
mVertices[4].pos = Vector2f(w, 0.0f); mVertices[5] = { { 0.0f, h }, { 0.0f, 0.0f }, color };
mVertices[4].tex = Vector2f(mValue * numStars, 1.0f); mVertices[6] = { { fw, 0.0f }, { numStars, 1.0f }, color };
mVertices[5] = mVertices[1]; mVertices[7] = { { fw, h }, { numStars, 0.0f }, color };
mVertices[6] = mVertices[4];
mVertices[7].pos = Vector2f(fw, h);
mVertices[7].tex = Vector2f(numStars, 0.0f);
mVertices[8] = mVertices[1];
mVertices[9] = mVertices[6];
mVertices[10].pos = Vector2f(fw, 0.0f);
mVertices[10].tex = Vector2f(numStars, 1.0f);
mVertices[11] = mVertices[7];
} }
void RatingComponent::updateColors() void RatingComponent::updateColors()
{ {
Renderer::buildGLColorArray(mColors, mColorShift, 12); const unsigned int color = Renderer::convertColor(mColorShift);
for(int i = 0; i < 8; ++i)
mVertices[i].col = color;
} }
void RatingComponent::render(const Transform4x4f& parentTrans) void RatingComponent::render(const Transform4x4f& parentTrans)
@ -116,30 +106,11 @@ void RatingComponent::render(const Transform4x4f& parentTrans)
trans.round(); trans.round();
Renderer::setMatrix(trans); Renderer::setMatrix(trans);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &mVertices[0].pos);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &mVertices[0].tex);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, mColors);
mFilledTexture->bind(); mFilledTexture->bind();
glDrawArrays(GL_TRIANGLES, 0, 6); Renderer::drawTriangleStrips(&mVertices[0], 4);
mUnfilledTexture->bind(); mUnfilledTexture->bind();
glDrawArrays(GL_TRIANGLES, 6, 6); Renderer::drawTriangleStrips(&mVertices[4], 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
renderChildren(trans); renderChildren(trans);
} }

View file

@ -2,9 +2,8 @@
#ifndef ES_APP_COMPONENTS_RATING_COMPONENT_H #ifndef ES_APP_COMPONENTS_RATING_COMPONENT_H
#define ES_APP_COMPONENTS_RATING_COMPONENT_H #define ES_APP_COMPONENTS_RATING_COMPONENT_H
#include "renderers/Renderer.h"
#include "GuiComponent.h" #include "GuiComponent.h"
#include "platform.h"
#include GLHEADER
class TextureResource; class TextureResource;
@ -43,14 +42,7 @@ private:
float mValue; float mValue;
struct Vertex Renderer::Vertex mVertices[8];
{
Vector2f pos;
Vector2f tex;
} mVertices[12];
GLubyte mColors[12*4];
unsigned int mColorShift; unsigned int mColorShift;

View file

@ -3,7 +3,6 @@
#include "components/ComponentGrid.h" #include "components/ComponentGrid.h"
#include "components/NinePatchComponent.h" #include "components/NinePatchComponent.h"
#include "components/TextComponent.h" #include "components/TextComponent.h"
#include "Renderer.h"
#include <SDL_timer.h> #include <SDL_timer.h>
GuiInfoPopup::GuiInfoPopup(Window* window, std::string message, int duration) : GuiInfoPopup::GuiInfoPopup(Window* window, std::string message, int duration) :

View file

@ -18,6 +18,7 @@
#include "VolumeControl.h" #include "VolumeControl.h"
#include <SDL_events.h> #include <SDL_events.h>
#include <algorithm> #include <algorithm>
#include "platform.h"
GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MENU"), mVersion(window) GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MENU"), mVersion(window)
{ {

View file

@ -306,9 +306,6 @@ int main(int argc, char* argv[])
return 1; return 1;
} }
std::string glExts = (const char*)glGetString(GL_EXTENSIONS);
LOG(LogInfo) << "Checking available OpenGL extensions...";
LOG(LogInfo) << " ARB_texture_non_power_of_two: " << (glExts.find("ARB_texture_non_power_of_two") != std::string::npos ? "ok" : "MISSING");
if(splashScreen) if(splashScreen)
{ {
std::string progressText = "Loading..."; std::string progressText = "Loading...";

View file

@ -5,7 +5,6 @@
#include "views/UIModeController.h" #include "views/UIModeController.h"
#include "views/ViewController.h" #include "views/ViewController.h"
#include "Log.h" #include "Log.h"
#include "Renderer.h"
#include "Settings.h" #include "Settings.h"
#include "SystemData.h" #include "SystemData.h"
#include "Window.h" #include "Window.h"

View file

@ -2,9 +2,9 @@
#ifndef ES_APP_VIEWS_VIEW_CONTROLLER_H #ifndef ES_APP_VIEWS_VIEW_CONTROLLER_H
#define ES_APP_VIEWS_VIEW_CONTROLLER_H #define ES_APP_VIEWS_VIEW_CONTROLLER_H
#include "renderers/Renderer.h"
#include "FileData.h" #include "FileData.h"
#include "GuiComponent.h" #include "GuiComponent.h"
#include "Renderer.h"
#include <vector> #include <vector>
class IGameListView; class IGameListView;

View file

@ -2,9 +2,9 @@
#ifndef ES_APP_VIEWS_GAME_LIST_IGAME_LIST_VIEW_H #ifndef ES_APP_VIEWS_GAME_LIST_IGAME_LIST_VIEW_H
#define ES_APP_VIEWS_GAME_LIST_IGAME_LIST_VIEW_H #define ES_APP_VIEWS_GAME_LIST_IGAME_LIST_VIEW_H
#include "renderers/Renderer.h"
#include "FileData.h" #include "FileData.h"
#include "GuiComponent.h" #include "GuiComponent.h"
#include "Renderer.h"
class ThemeData; class ThemeData;
class Window; class Window;

View file

@ -14,7 +14,6 @@ set(CORE_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/src/MameNames.h ${CMAKE_CURRENT_SOURCE_DIR}/src/MameNames.h
${CMAKE_CURRENT_SOURCE_DIR}/src/platform.h ${CMAKE_CURRENT_SOURCE_DIR}/src/platform.h
${CMAKE_CURRENT_SOURCE_DIR}/src/PowerSaver.h ${CMAKE_CURRENT_SOURCE_DIR}/src/PowerSaver.h
${CMAKE_CURRENT_SOURCE_DIR}/src/Renderer.h
${CMAKE_CURRENT_SOURCE_DIR}/src/Settings.h ${CMAKE_CURRENT_SOURCE_DIR}/src/Settings.h
${CMAKE_CURRENT_SOURCE_DIR}/src/Sound.h ${CMAKE_CURRENT_SOURCE_DIR}/src/Sound.h
${CMAKE_CURRENT_SOURCE_DIR}/src/ThemeData.h ${CMAKE_CURRENT_SOURCE_DIR}/src/ThemeData.h
@ -64,6 +63,9 @@ set(CORE_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector3f.h ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector3f.h
${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector4f.h ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector4f.h
# Renderers
${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Renderer.h
# Resources # Resources
${CMAKE_CURRENT_SOURCE_DIR}/src/resources/Font.h ${CMAKE_CURRENT_SOURCE_DIR}/src/resources/Font.h
${CMAKE_CURRENT_SOURCE_DIR}/src/resources/ResourceManager.h ${CMAKE_CURRENT_SOURCE_DIR}/src/resources/ResourceManager.h
@ -90,8 +92,6 @@ set(CORE_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/MameNames.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/MameNames.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/platform.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/platform.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/PowerSaver.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/PowerSaver.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Renderer_draw_gl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Renderer_init_sdlgl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Scripting.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Scripting.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Settings.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Settings.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Sound.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Sound.cpp
@ -137,6 +137,11 @@ set(CORE_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector3f.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector3f.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector4f.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/math/Vector4f.cpp
# Renderer
${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Renderer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Renderer_GL21.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Renderer_GLES10.cpp
# Resources # Resources
${CMAKE_CURRENT_SOURCE_DIR}/src/resources/Font.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/resources/Font.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/resources/ResourceManager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/resources/ResourceManager.cpp

View file

@ -2,8 +2,8 @@
#include "animations/Animation.h" #include "animations/Animation.h"
#include "animations/AnimationController.h" #include "animations/AnimationController.h"
#include "renderers/Renderer.h"
#include "Log.h" #include "Log.h"
#include "Renderer.h"
#include "ThemeData.h" #include "ThemeData.h"
#include "Window.h" #include "Window.h"
#include <algorithm> #include <algorithm>

View file

@ -1,7 +1,6 @@
#include "HelpStyle.h" #include "HelpStyle.h"
#include "resources/Font.h" #include "resources/Font.h"
#include "Renderer.h"
HelpStyle::HelpStyle() HelpStyle::HelpStyle()
{ {

View file

@ -1,43 +0,0 @@
#pragma once
#ifndef ES_CORE_RENDERER_H
#define ES_CORE_RENDERER_H
#include "math/Vector2i.h"
#include "platform.h"
#include GLHEADER
class Font;
class GuiComponent;
class Transform4x4f;
//The Renderer provides several higher-level functions for drawing (rectangles, text, etc.).
//Renderer_draw_gl.cpp has most of the higher-level functions and wrappers.
//Renderer_init_*.cpp has platform-specific renderer initialziation/deinitialziation code. (e.g. the Raspberry Pi sets up dispmanx/OpenGL ES)
namespace Renderer
{
bool init();
void deinit();
unsigned int getWindowWidth();
unsigned int getWindowHeight();
unsigned int getScreenWidth();
unsigned int getScreenHeight();
unsigned int getScreenOffsetX();
unsigned int getScreenOffsetY();
unsigned int getScreenRotate();
void buildGLColorArray(GLubyte* ptr, unsigned int color, unsigned int vertCount);
//graphics commands
void swapBuffers();
void pushClipRect(Vector2i pos, Vector2i dim);
void popClipRect();
void setMatrix(const Transform4x4f& transform);
void drawRect(int x, int y, int w, int h, unsigned int color, GLenum blend_sfactor = GL_SRC_ALPHA, GLenum blend_dfactor = GL_ONE_MINUS_SRC_ALPHA);
void drawRect(float x, float y, float w, float h, unsigned int color, GLenum blend_sfactor = GL_SRC_ALPHA, GLenum blend_dfactor = GL_ONE_MINUS_SRC_ALPHA);
}
#endif // ES_CORE_RENDERER_H

View file

@ -1,154 +0,0 @@
#include "Renderer.h"
#include "math/Misc.h"
#include "Log.h"
#include <stack>
namespace Renderer {
struct ClipRect {
ClipRect(const int x, const int y, const int w, const int h) :
x(x), y(y), w(w), h(h) {};
int x;
int y;
int w;
int h;
};
std::stack<ClipRect> clipStack;
void setColor4bArray(GLubyte* array, unsigned int color)
{
array[0] = ((color & 0xff000000) >> 24) & 255;
array[1] = ((color & 0x00ff0000) >> 16) & 255;
array[2] = ((color & 0x0000ff00) >> 8) & 255;
array[3] = ((color & 0x000000ff) ) & 255;
}
void buildGLColorArray(GLubyte* ptr, unsigned int color, unsigned int vertCount)
{
unsigned int colorGl;
setColor4bArray((GLubyte*)&colorGl, color);
for(unsigned int i = 0; i < vertCount; i++)
{
((GLuint*)ptr)[i] = colorGl;
}
}
void pushClipRect(Vector2i pos, Vector2i dim)
{
ClipRect box(pos.x(), pos.y(), dim.x(), dim.y());
if(box.w == 0)
box.w = Renderer::getScreenWidth() - box.x;
if(box.h == 0)
box.h = Renderer::getScreenHeight() - box.y;
//glScissor starts at the bottom left of the window
//so (0, 0, 1, 1) is the bottom left pixel
//everything else uses y+ = down, so flip it to be consistent
switch(Renderer::getScreenRotate())
{
case 0: { box = ClipRect(box.x, Renderer::getWindowHeight() - (box.y + box.h), box.w, box.h); } break;
case 1: { box = ClipRect(Renderer::getScreenHeight() - (box.y + box.h), Renderer::getWindowWidth() - (box.x + box.w), box.h, box.w); } break;
case 2: { box = ClipRect(Renderer::getScreenWidth() - (box.x + box.w), Renderer::getWindowHeight() - Renderer::getScreenHeight() + box.y, box.w, box.h); } break;
case 3: { box = ClipRect(box.y, Renderer::getWindowWidth() - Renderer::getScreenWidth() + box.x, box.h, box.w); } break;
}
switch(Renderer::getScreenRotate())
{
case 0: { box.x += Renderer::getScreenOffsetX(); box.y -= Renderer::getScreenOffsetY(); } break;
case 1: { box.x += Renderer::getScreenOffsetY(); box.y -= Renderer::getScreenOffsetX(); } break;
case 2: { box.x += Renderer::getScreenOffsetX(); box.y -= Renderer::getScreenOffsetY(); } break;
case 3: { box.x += Renderer::getScreenOffsetY(); box.y -= Renderer::getScreenOffsetX(); } break;
}
//make sure the box fits within clipStack.top(), and clip further accordingly
if(clipStack.size())
{
const ClipRect& 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(box.w < 0)
box.w = 0;
if(box.h < 0)
box.h = 0;
clipStack.push(box);
glScissor(box.x, box.y, box.w, box.h);
glEnable(GL_SCISSOR_TEST);
}
void popClipRect()
{
if(clipStack.empty())
{
LOG(LogError) << "Tried to popClipRect while the stack was empty!";
return;
}
clipStack.pop();
if(clipStack.empty())
{
glDisable(GL_SCISSOR_TEST);
}else{
const ClipRect& top = clipStack.top();
glScissor(top.x, top.y, top.w, top.h);
}
}
void drawRect(float x, float y, float w, float h, unsigned int color, GLenum blend_sfactor, GLenum blend_dfactor)
{
drawRect((int)Math::round(x), (int)Math::round(y), (int)Math::round(w), (int)Math::round(h), color, blend_sfactor, blend_dfactor);
}
void drawRect(int x, int y, int w, int h, unsigned int color, GLenum blend_sfactor, GLenum blend_dfactor)
{
#ifdef USE_OPENGL_ES
GLshort points[12];
#else
GLint points[12];
#endif
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);
glEnable(GL_BLEND);
glBlendFunc(blend_sfactor, blend_dfactor);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
#ifdef USE_OPENGL_ES
glVertexPointer(2, GL_SHORT, 0, points);
#else
glVertexPointer(2, GL_INT, 0, points);
#endif
glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisable(GL_BLEND);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
void setMatrix(const Transform4x4f& matrix)
{
glLoadMatrixf((GLfloat*)&matrix);
}
};

View file

@ -1,222 +0,0 @@
#include "Renderer.h"
#include "resources/ResourceManager.h"
#include "ImageIO.h"
#include "Log.h"
#include "Settings.h"
#include <SDL.h>
#ifdef USE_OPENGL_ES
#define glOrtho glOrthof
#endif
namespace Renderer
{
static bool initialCursorState;
unsigned int windowWidth = 0;
unsigned int windowHeight = 0;
unsigned int screenWidth = 0;
unsigned int screenHeight = 0;
unsigned int screenOffsetX = 0;
unsigned int screenOffsetY = 0;
unsigned int screenRotate = 0;
unsigned int getWindowWidth() { return windowWidth; }
unsigned int getWindowHeight() { return windowHeight; }
unsigned int getScreenWidth() { return screenWidth; }
unsigned int getScreenHeight() { return screenHeight; }
unsigned int getScreenOffsetX() { return screenOffsetX; }
unsigned int getScreenOffsetY() { return screenOffsetY; }
unsigned int getScreenRotate() { return screenRotate; }
SDL_Window* sdlWindow = NULL;
SDL_GLContext sdlContext = NULL;
bool createSurface()
{
LOG(LogInfo) << "Creating surface...";
if(SDL_Init(SDL_INIT_VIDEO) != 0)
{
LOG(LogError) << "Error initializing SDL!\n " << SDL_GetError();
return false;
}
//hide mouse cursor early
initialCursorState = SDL_ShowCursor(0) == 1;
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
// multisample anti-aliasing
//SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
//SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 2);
#ifdef USE_OPENGL_ES
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
#endif
SDL_DisplayMode dispMode;
SDL_GetDesktopDisplayMode(0, &dispMode);
windowWidth = Settings::getInstance()->getInt("WindowWidth") ? Settings::getInstance()->getInt("WindowWidth") : dispMode.w;
windowHeight = Settings::getInstance()->getInt("WindowHeight") ? Settings::getInstance()->getInt("WindowHeight") : dispMode.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;
screenRotate = Settings::getInstance()->getInt("ScreenRotate") ? Settings::getInstance()->getInt("ScreenRotate") : 0;
sdlWindow = SDL_CreateWindow("EmulationStation",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
windowWidth, windowHeight,
SDL_WINDOW_OPENGL | (Settings::getInstance()->getBool("Windowed") ? 0 : (Settings::getInstance()->getBool("FullscreenBorderless") ? SDL_WINDOW_BORDERLESS : SDL_WINDOW_FULLSCREEN)));
if(sdlWindow == NULL)
{
LOG(LogError) << "Error creating SDL window!\n\t" << SDL_GetError();
return false;
}
LOG(LogInfo) << "Created window successfully.";
//support screen rotation
if((screenRotate == 1) || (screenRotate == 3))
{
int temp;
temp = windowWidth;
windowWidth = windowHeight;
windowHeight = temp;
temp = screenWidth;
screenWidth = screenHeight;
screenHeight = temp;
temp = screenOffsetX;
screenOffsetX = screenOffsetY;
screenOffsetY = temp;
}
//set an icon for the window
size_t width = 0;
size_t height = 0;
ResourceData resData = ResourceManager::getInstance()->getFileData(":/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);
//SDL interprets each pixel as a 32-bit number, so our masks must depend on the endianness (byte order) of the machine
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
Uint32 rmask = 0xff000000; Uint32 gmask = 0x00ff0000; Uint32 bmask = 0x0000ff00; Uint32 amask = 0x000000ff;
#else
Uint32 rmask = 0x000000ff; Uint32 gmask = 0x0000ff00; Uint32 bmask = 0x00ff0000; Uint32 amask = 0xff000000;
#endif
//try creating SDL surface from logo data
SDL_Surface * logoSurface = SDL_CreateRGBSurfaceFrom((void *)rawData.data(), (int)width, (int)height, 32, (int)(width * 4), rmask, gmask, bmask, amask);
if (logoSurface != NULL)
{
SDL_SetWindowIcon(sdlWindow, logoSurface);
SDL_FreeSurface(logoSurface);
}
}
sdlContext = SDL_GL_CreateContext(sdlWindow);
// vsync
if(Settings::getInstance()->getBool("VSync"))
{
// SDL_GL_SetSwapInterval(0) for immediate updates (no vsync, default),
// 1 for updates synchronized with the vertical retrace,
// or -1 for late swap tearing.
// SDL_GL_SetSwapInterval returns 0 on success, -1 on error.
// if vsync is requested, try normal vsync; if that doesn't work, try late swap tearing
// if that doesn't work, report an error
if(SDL_GL_SetSwapInterval(1) != 0 && SDL_GL_SetSwapInterval(-1) != 0)
LOG(LogWarning) << "Tried to enable vsync, but failed! (" << SDL_GetError() << ")";
}
else
SDL_GL_SetSwapInterval(0);
return true;
}
void destroySurface()
{
SDL_GL_DeleteContext(sdlContext);
sdlContext = NULL;
SDL_DestroyWindow(sdlWindow);
sdlWindow = NULL;
//show mouse cursor
SDL_ShowCursor(initialCursorState);
SDL_Quit();
}
bool init()
{
if(!createSurface())
return false;
//gotta flip y since y=0 is at the bottom
switch(screenRotate)
{
case 0:
{
glViewport(screenOffsetX, windowHeight - screenHeight - screenOffsetY, screenWidth, screenHeight);
glMatrixMode(GL_PROJECTION);
glOrtho(0, screenWidth, screenHeight, 0, -1.0, 1.0);
}
break;
case 1:
{
glViewport(screenOffsetY, windowWidth - screenWidth - screenOffsetX, screenHeight, screenWidth);
glMatrixMode(GL_PROJECTION);
glOrtho(0, screenHeight, screenWidth, 0, -1.0, 1.0);
glRotatef(90, 0, 0, 1);
glTranslatef(0, screenHeight * -1.0f, 0);
}
break;
case 2:
{
glViewport(screenOffsetX, windowHeight - screenHeight - screenOffsetY, screenWidth, screenHeight);
glMatrixMode(GL_PROJECTION);
glOrtho(0, screenWidth, screenHeight, 0, -1.0, 1.0);
glRotatef(180, 0, 0, 1);
glTranslatef(screenWidth * -1.0f, screenHeight * -1.0f, 0);
}
break;
case 3:
{
glViewport(screenOffsetY, windowWidth - screenWidth - screenOffsetX, screenHeight, screenWidth);
glMatrixMode(GL_PROJECTION);
glOrtho(0, screenHeight, screenWidth, 0, -1.0, 1.0);
glRotatef(270, 0, 0, 1);
glTranslatef(screenWidth * -1.0f, 0, 0);
}
break;
}
glMatrixMode(GL_MODELVIEW);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
return true;
}
void deinit()
{
destroySurface();
}
void swapBuffers()
{
SDL_GL_SwapWindow(sdlWindow);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
};

View file

@ -6,7 +6,6 @@
#include "resources/TextureResource.h" #include "resources/TextureResource.h"
#include "InputManager.h" #include "InputManager.h"
#include "Log.h" #include "Log.h"
#include "Renderer.h"
#include "Scripting.h" #include "Scripting.h"
#include <algorithm> #include <algorithm>
#include <iomanip> #include <iomanip>

View file

@ -3,7 +3,6 @@
#include "components/AnimatedImageComponent.h" #include "components/AnimatedImageComponent.h"
#include "components/ImageComponent.h" #include "components/ImageComponent.h"
#include "components/TextComponent.h" #include "components/TextComponent.h"
#include "Renderer.h"
// animation definition // animation definition
AnimationFrame BUSY_ANIMATION_FRAMES[] = { AnimationFrame BUSY_ANIMATION_FRAMES[] = {

View file

@ -2,7 +2,6 @@
#include "resources/Font.h" #include "resources/Font.h"
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
#include "Renderer.h"
ButtonComponent::ButtonComponent(Window* window, const std::string& text, const std::string& helpText, const std::function<void()>& func) : GuiComponent(window), ButtonComponent::ButtonComponent(Window* window, const std::string& text, const std::string& helpText, const std::function<void()>& func) : GuiComponent(window),
mBox(window, ":/button.png"), mBox(window, ":/button.png"),

View file

@ -1,6 +1,5 @@
#include "components/ComponentGrid.h" #include "components/ComponentGrid.h"
#include "Renderer.h"
#include "Settings.h" #include "Settings.h"
using namespace GridFlags; using namespace GridFlags;
@ -151,6 +150,7 @@ void ComponentGrid::updateSeparators()
{ {
mLines.clear(); mLines.clear();
const unsigned int color = Renderer::convertColor(0xC6C7C6FF);
bool drawAll = Settings::getInstance()->getBool("DebugGrid"); bool drawAll = Settings::getInstance()->getBool("DebugGrid");
Vector2f pos; Vector2f pos;
@ -174,28 +174,25 @@ void ComponentGrid::updateSeparators()
if(it->border & BORDER_TOP || drawAll) if(it->border & BORDER_TOP || drawAll)
{ {
mLines.push_back(Vert(pos.x(), pos.y())); mLines.push_back( { { pos.x(), pos.y() }, { 0.0f, 0.0f }, color } );
mLines.push_back(Vert(pos.x() + size.x(), pos.y())); mLines.push_back( { { pos.x() + size.x(), pos.y() }, { 0.0f, 0.0f }, color } );
} }
if(it->border & BORDER_BOTTOM || drawAll) if(it->border & BORDER_BOTTOM || drawAll)
{ {
mLines.push_back(Vert(pos.x(), pos.y() + size.y())); mLines.push_back( { { pos.x(), pos.y() + size.y() }, { 0.0f, 0.0f }, color } );
mLines.push_back(Vert(pos.x() + size.x(), mLines.back().y)); mLines.push_back( { { pos.x() + size.x(), mLines.back().pos.y() }, { 0.0f, 0.0f }, color } );
} }
if(it->border & BORDER_LEFT || drawAll) if(it->border & BORDER_LEFT || drawAll)
{ {
mLines.push_back(Vert(pos.x(), pos.y())); mLines.push_back( { { pos.x(), pos.y() }, { 0.0f, 0.0f }, color } );
mLines.push_back(Vert(pos.x(), pos.y() + size.y())); mLines.push_back( { { pos.x(), pos.y() + size.y() }, { 0.0f, 0.0f }, color } );
} }
if(it->border & BORDER_RIGHT || drawAll) if(it->border & BORDER_RIGHT || drawAll)
{ {
mLines.push_back(Vert(pos.x() + size.x(), pos.y())); mLines.push_back( { { pos.x() + size.x(), pos.y() }, { 0.0f, 0.0f }, color } );
mLines.push_back(Vert(mLines.back().x, pos.y() + size.y())); mLines.push_back( { { mLines.back().pos.x(), pos.y() + size.y() }, { 0.0f, 0.0f }, color } );
} }
} }
mLineColors.reserve(mLines.size());
Renderer::buildGLColorArray((GLubyte*)mLineColors.data(), 0xC6C7C6FF, (unsigned int)mLines.size());
} }
void ComponentGrid::onSizeChanged() void ComponentGrid::onSizeChanged()
@ -365,20 +362,8 @@ void ComponentGrid::render(const Transform4x4f& parentTrans)
if(mLines.size()) if(mLines.size())
{ {
Renderer::setMatrix(trans); Renderer::setMatrix(trans);
Renderer::bindTexture(0);
glEnable(GL_BLEND); Renderer::drawLines(&mLines[0], mLines.size());
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, &mLines[0].x);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, mLineColors.data());
glDrawArrays(GL_LINES, 0, (GLsizei)mLines.size());
glDisable(GL_BLEND);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
} }
} }

View file

@ -3,6 +3,7 @@
#define ES_CORE_COMPONENTS_COMPONENT_GRID_H #define ES_CORE_COMPONENTS_COMPONENT_GRID_H
#include "math/Vector2i.h" #include "math/Vector2i.h"
#include "renderers/Renderer.h"
#include "GuiComponent.h" #include "GuiComponent.h"
namespace GridFlags namespace GridFlags
@ -96,15 +97,7 @@ private:
float* mRowHeights; float* mRowHeights;
float* mColWidths; float* mColWidths;
struct Vert std::vector<Renderer::Vertex> mLines;
{
Vert(float xi = 0, float yi = 0) : x(xi), y(yi) {};
float x;
float y;
};
std::vector<Vert> mLines;
std::vector<unsigned int> mLineColors;
// Update position & size // Update position & size
void updateCellComponent(const GridEntry& cell); void updateCellComponent(const GridEntry& cell);

View file

@ -1,7 +1,5 @@
#include "components/ComponentList.h" #include "components/ComponentList.h"
#include "Renderer.h"
#define TOTAL_HORIZONTAL_PADDING_PX 20 #define TOTAL_HORIZONTAL_PADDING_PX 20
ComponentList::ComponentList(Window* window) : IList<ComponentListRow, void*>(window, LIST_SCROLL_STYLE_SLOW, LIST_NEVER_LOOP) ComponentList::ComponentList(Window* window) : IList<ComponentListRow, void*>(window, LIST_SCROLL_STYLE_SLOW, LIST_NEVER_LOOP)
@ -204,10 +202,8 @@ void ComponentList::render(const Transform4x4f& parentTrans)
// (1 - dst) + 0x77 // (1 - dst) + 0x77
const float selectedRowHeight = getRowHeight(mEntries.at(mCursor).data); const float selectedRowHeight = getRowHeight(mEntries.at(mCursor).data);
Renderer::drawRect(0.0f, mSelectorBarOffset, mSize.x(), selectedRowHeight, 0xFFFFFFFF, Renderer::drawRect(0.0f, mSelectorBarOffset, mSize.x(), selectedRowHeight, 0xFFFFFFFF, Renderer::Blend::ONE_MINUS_DST_COLOR, Renderer::Blend::ZERO);
GL_ONE_MINUS_DST_COLOR, GL_ZERO); Renderer::drawRect(0.0f, mSelectorBarOffset, mSize.x(), selectedRowHeight, 0x777777FF, Renderer::Blend::ONE, Renderer::Blend::ONE);
Renderer::drawRect(0.0f, mSelectorBarOffset, mSize.x(), selectedRowHeight, 0x777777FF,
GL_ONE, GL_ONE);
// hack to draw 2px dark on left/right of the bar // hack to draw 2px dark on left/right of the bar
Renderer::drawRect(0.0f, mSelectorBarOffset, 2.0f, selectedRowHeight, 0x878787FF); Renderer::drawRect(0.0f, mSelectorBarOffset, 2.0f, selectedRowHeight, 0x878787FF);

View file

@ -2,7 +2,6 @@
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
#include "Log.h" #include "Log.h"
#include "Renderer.h"
#include "Settings.h" #include "Settings.h"
DateTimeComponent::DateTimeComponent(Window* window) : TextComponent(window), mDisplayRelative(false) DateTimeComponent::DateTimeComponent(Window* window) : TextComponent(window), mDisplayRelative(false)

View file

@ -2,7 +2,6 @@
#include "resources/Font.h" #include "resources/Font.h"
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
#include "Renderer.h"
DateTimeEditComponent::DateTimeEditComponent(Window* window, DisplayMode dispMode) : GuiComponent(window), DateTimeEditComponent::DateTimeEditComponent(Window* window, DisplayMode dispMode) : GuiComponent(window),
mEditing(false), mEditIndex(0), mDisplayMode(dispMode), mRelativeUpdateAccumulator(0), mEditing(false), mEditIndex(0), mDisplayMode(dispMode), mRelativeUpdateAccumulator(0),

View file

@ -2,7 +2,6 @@
#include "resources/TextureResource.h" #include "resources/TextureResource.h"
#include "ThemeData.h" #include "ThemeData.h"
#include "Renderer.h"
GridTileComponent::GridTileComponent(Window* window) : GuiComponent(window), mBackground(window) GridTileComponent::GridTileComponent(Window* window) : GuiComponent(window), mBackground(window)
{ {

View file

@ -2,7 +2,6 @@
#include "resources/TextureResource.h" #include "resources/TextureResource.h"
#include "Log.h" #include "Log.h"
#include "Renderer.h"
#include "Settings.h" #include "Settings.h"
#include "ThemeData.h" #include "ThemeData.h"
@ -268,51 +267,36 @@ void ImageComponent::updateVertices()
// we go through this mess to make sure everything is properly rounded // we go through this mess to make sure everything is properly rounded
// if we just round vertices at the end, edge cases occur near sizes of 0.5 // if we just round vertices at the end, edge cases occur near sizes of 0.5
Vector2f size(Math::round(mSize.x()), Math::round(mSize.y())); const Vector2f size = { Math::round(mSize.x()), Math::round(mSize.y()) };
Vector2f topLeft(size * mTopLeftCrop); const Vector2f topLeft = { size * mTopLeftCrop };
Vector2f bottomRight(size * mBottomRightCrop); const Vector2f bottomRight = { size * mBottomRightCrop };
const float px = mTexture->isTiled() ? mSize.x() / getTextureSize().x() : 1.0f;
const float py = mTexture->isTiled() ? mSize.y() / getTextureSize().y() : 1.0f;
const unsigned int color = Renderer::convertColor(mColorShift);
mVertices[0].pos = Vector2f(topLeft.x(), topLeft.y()); mVertices[0] = { { topLeft.x(), topLeft.y() }, { mTopLeftCrop.x(), py - mTopLeftCrop.y() }, color };
mVertices[1].pos = Vector2f(topLeft.x(), bottomRight.y()); mVertices[1] = { { topLeft.x(), bottomRight.y() }, { mTopLeftCrop.x(), 1.0f - mBottomRightCrop.y() }, color };
mVertices[2].pos = Vector2f(bottomRight.x(), topLeft.y()); mVertices[2] = { { bottomRight.x(), topLeft.y() }, { mBottomRightCrop.x() * px, py - mTopLeftCrop.y() }, color };
mVertices[3] = { { bottomRight.x(), bottomRight.y() }, { mBottomRightCrop.x() * px, 1.0f - mBottomRightCrop.y() }, color };
mVertices[3].pos = Vector2f(bottomRight.x(), topLeft.y());
mVertices[4].pos = Vector2f(topLeft.x(), bottomRight.y());
mVertices[5].pos = Vector2f(bottomRight.x(), bottomRight.y());
float px, py;
if(mTexture->isTiled())
{
px = mSize.x() / getTextureSize().x();
py = mSize.y() / getTextureSize().y();
}else{
px = 1;
py = 1;
}
mVertices[0].tex = Vector2f(mTopLeftCrop.x(), py - mTopLeftCrop.y());
mVertices[1].tex = Vector2f(mTopLeftCrop.x(), 1 - mBottomRightCrop.y());
mVertices[2].tex = Vector2f(px * mBottomRightCrop.x(), py - mTopLeftCrop.y());
mVertices[3].tex = Vector2f(px * mBottomRightCrop.x(), py - mTopLeftCrop.y());
mVertices[4].tex = Vector2f(mTopLeftCrop.x(), 1 - mBottomRightCrop.y());
mVertices[5].tex = Vector2f(px * mBottomRightCrop.x(), 1 - mBottomRightCrop.y());
if(mFlipX) if(mFlipX)
{ {
for(int i = 0; i < 6; i++) for(int i = 0; i < 4; i++)
mVertices[i].tex[0] = px - mVertices[i].tex[0]; mVertices[i].tex[0] = px - mVertices[i].tex[0];
} }
if(mFlipY) if(mFlipY)
{ {
for(int i = 0; i < 6; i++) for(int i = 0; i < 4; i++)
mVertices[i].tex[1] = py - mVertices[i].tex[1]; mVertices[i].tex[1] = py - mVertices[i].tex[1];
} }
} }
void ImageComponent::updateColors() void ImageComponent::updateColors()
{ {
Renderer::buildGLColorArray(mColors, mColorShift, 6); const unsigned int color = Renderer::convertColor(mColorShift);
for(int i = 0; i < 4; ++i)
mVertices[i].col = color;
} }
void ImageComponent::render(const Transform4x4f& parentTrans) void ImageComponent::render(const Transform4x4f& parentTrans)
@ -334,27 +318,8 @@ void ImageComponent::render(const Transform4x4f& parentTrans)
// texture is bound in this case but we want to handle a fade so it doesn't just 'jump' in // texture is bound in this case but we want to handle a fade so it doesn't just 'jump' in
// when it finally loads // when it finally loads
fadeIn(mTexture->bind()); fadeIn(mTexture->bind());
Renderer::drawTriangleStrips(&mVertices[0], 4);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &mVertices[0].pos);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &mVertices[0].tex);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, mColors);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
}else{ }else{
LOG(LogError) << "Image texture is not initialized!"; LOG(LogError) << "Image texture is not initialized!";
mTexture.reset(); mTexture.reset();

View file

@ -2,10 +2,9 @@
#ifndef ES_CORE_COMPONENTS_IMAGE_COMPONENT_H #ifndef ES_CORE_COMPONENTS_IMAGE_COMPONENT_H
#define ES_CORE_COMPONENTS_IMAGE_COMPONENT_H #define ES_CORE_COMPONENTS_IMAGE_COMPONENT_H
#include "renderers/Renderer.h"
#include "math/Vector2i.h" #include "math/Vector2i.h"
#include "GuiComponent.h" #include "GuiComponent.h"
#include "platform.h"
#include GLHEADER
class TextureResource; class TextureResource;
@ -83,13 +82,7 @@ private:
// Used internally whenever the resizing parameters or texture change. // Used internally whenever the resizing parameters or texture change.
void resize(); void resize();
struct Vertex Renderer::Vertex mVertices[4];
{
Vector2f pos;
Vector2f tex;
} mVertices[6];
GLubyte mColors[6*4];
void updateVertices(); void updateVertices();
void updateColors(); void updateColors();

View file

@ -7,7 +7,6 @@
#include "components/NinePatchComponent.h" #include "components/NinePatchComponent.h"
#include "components/TextComponent.h" #include "components/TextComponent.h"
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
#include "Renderer.h"
class ButtonComponent; class ButtonComponent;
class ImageComponent; class ImageComponent;

View file

@ -2,14 +2,13 @@
#include "resources/TextureResource.h" #include "resources/TextureResource.h"
#include "Log.h" #include "Log.h"
#include "Renderer.h"
#include "ThemeData.h" #include "ThemeData.h"
NinePatchComponent::NinePatchComponent(Window* window, const std::string& path, unsigned int edgeColor, unsigned int centerColor) : GuiComponent(window), NinePatchComponent::NinePatchComponent(Window* window, const std::string& path, unsigned int edgeColor, unsigned int centerColor) : GuiComponent(window),
mCornerSize(16, 16), mCornerSize(16, 16),
mEdgeColor(edgeColor), mCenterColor(centerColor), mEdgeColor(edgeColor), mCenterColor(centerColor),
mPath(path), mPath(path),
mVertices(NULL), mColors(NULL) mVertices(NULL)
{ {
if(!mPath.empty()) if(!mPath.empty())
buildVertices(); buildVertices();
@ -19,15 +18,18 @@ NinePatchComponent::~NinePatchComponent()
{ {
if (mVertices != NULL) if (mVertices != NULL)
delete[] mVertices; delete[] mVertices;
if (mColors != NULL)
delete[] mColors;
} }
void NinePatchComponent::updateColors() void NinePatchComponent::updateColors()
{ {
Renderer::buildGLColorArray(mColors, mEdgeColor, 6 * 9); const unsigned int edgeColor = Renderer::convertColor(mEdgeColor);
Renderer::buildGLColorArray(&mColors[4 * 6 * 4], mCenterColor, 6); const unsigned int centerColor = Renderer::convertColor(mCenterColor);
for(int i = 0; i < 6*9; ++i)
mVertices[i].col = edgeColor;
for(int i = 6*4; i < 6; ++i)
mVertices[(6*4)+i].col = mCenterColor;
} }
void NinePatchComponent::buildVertices() void NinePatchComponent::buildVertices()
@ -35,61 +37,48 @@ void NinePatchComponent::buildVertices()
if(mVertices != NULL) if(mVertices != NULL)
delete[] mVertices; delete[] mVertices;
if(mColors != NULL)
delete[] mColors;
mTexture = TextureResource::get(mPath); mTexture = TextureResource::get(mPath);
if(mTexture->getSize() == Vector2i::Zero()) if(mTexture->getSize() == Vector2i::Zero())
{ {
mVertices = NULL; mVertices = NULL;
mColors = NULL;
LOG(LogWarning) << "NinePatchComponent missing texture!"; LOG(LogWarning) << "NinePatchComponent missing texture!";
return; return;
} }
mVertices = new Vertex[6 * 9]; mVertices = new Renderer::Vertex[6 * 9];
mColors = new GLubyte[6 * 9 * 4];
updateColors();
const Vector2f texSize = Vector2f((float)mTexture->getSize().x(), (float)mTexture->getSize().y()); const Vector2f texSize = Vector2f((float)mTexture->getSize().x(), (float)mTexture->getSize().y());
float imgSizeX[3] = {mCornerSize.x(), mSize.x() - mCornerSize.x() * 2, mCornerSize.x()}; const float imgSizeX[3] = { mCornerSize.x(), mSize.x() - mCornerSize.x() * 2, mCornerSize.x()};
float imgSizeY[3] = {mCornerSize.y(), mSize.y() - mCornerSize.y() * 2, mCornerSize.y()}; const float imgSizeY[3] = { mCornerSize.y(), mSize.y() - mCornerSize.y() * 2, mCornerSize.y()};
float imgPosX[3] = {0, imgSizeX[0], imgSizeX[0] + imgSizeX[1]}; const float imgPosX[3] = { 0, imgSizeX[0], imgSizeX[0] + imgSizeX[1]};
float imgPosY[3] = {0, imgSizeY[0], imgSizeY[0] + imgSizeY[1]}; const float imgPosY[3] = { 0, imgSizeY[0], imgSizeY[0] + imgSizeY[1]};
//the "1 +" in posY and "-" in sizeY is to deal with texture coordinates having a bottom left corner origin vs. verticies having a top left origin //the "1 +" in posY and "-" in sizeY is to deal with texture coordinates having a bottom left corner origin vs. verticies having a top left origin
float texSizeX[3] = {mCornerSize.x() / texSize.x(), (texSize.x() - mCornerSize.x() * 2) / texSize.x(), mCornerSize.x() / texSize.x()}; const float texSizeX[3] = { mCornerSize.x() / texSize.x(), (texSize.x() - mCornerSize.x() * 2) / texSize.x(), mCornerSize.x() / texSize.x() };
float texSizeY[3] = {-mCornerSize.y() / texSize.y(), -(texSize.y() - mCornerSize.y() * 2) / texSize.y(), -mCornerSize.y() / texSize.y()}; const float texSizeY[3] = { -mCornerSize.y() / texSize.y(), -(texSize.y() - mCornerSize.y() * 2) / texSize.y(), -mCornerSize.y() / texSize.y() };
float texPosX[3] = {0, texSizeX[0], texSizeX[0] + texSizeX[1]}; const float texPosX[3] = { 0, texSizeX[0], texSizeX[0] + texSizeX[1] };
float texPosY[3] = {1, 1 + texSizeY[0], 1 + texSizeY[0] + texSizeY[1]}; const float texPosY[3] = { 1, 1 + texSizeY[0], 1 + texSizeY[0] + texSizeY[1] };
int v = 0; int v = 0;
for(int slice = 0; slice < 9; slice++) for(int slice = 0; slice < 9; slice++)
{ {
int sliceX = slice % 3; const int sliceX = slice % 3;
int sliceY = slice / 3; const int sliceY = slice / 3;
const Vector2f imgPos = Vector2f(imgPosX[sliceX], imgPosY[sliceY]);
const Vector2f imgSize = Vector2f(imgSizeX[sliceX], imgSizeY[sliceY]);
const Vector2f texPos = Vector2f(texPosX[sliceX], texPosY[sliceY]);
const Vector2f texSize = Vector2f(texSizeX[sliceX], texSizeY[sliceY]);
Vector2f imgPos = Vector2f(imgPosX[sliceX], imgPosY[sliceY]); mVertices[v + 1] = { { imgPos.x() , imgPos.y() }, { texPos.x(), texPos.y() }, 0 };
Vector2f imgSize = Vector2f(imgSizeX[sliceX], imgSizeY[sliceY]); mVertices[v + 2] = { { imgPos.x() , imgPos.y() + imgSize.y() }, { texPos.x(), texPos.y() + texSize.y() }, 0 };
mVertices[v + 3] = { { imgPos.x() + imgSize.x(), imgPos.y() }, { texPos.x() + texSize.x(), texPos.y() }, 0 };
mVertices[v + 4] = { { imgPos.x() + imgSize.x(), imgPos.y() + imgSize.y() }, { texPos.x() + texSize.x(), texPos.y() + texSize.y() }, 0 };
mVertices[v + 0].pos = imgPos; // make duplicates of first and last vertex so this can be rendered as a triangle strip
mVertices[v + 1].pos = imgPos + Vector2f(0, imgSize.y()); mVertices[v + 0] = mVertices[v + 1];
mVertices[v + 2].pos = imgPos + Vector2f(imgSize.x(), 0); mVertices[v + 5] = mVertices[v + 4];
mVertices[v + 3].pos = mVertices[v + 2].pos;
mVertices[v + 4].pos = mVertices[v + 1].pos;
mVertices[v + 5].pos = imgPos + imgSize;
Vector2f texPos = Vector2f(texPosX[sliceX], texPosY[sliceY]);
Vector2f texSize = Vector2f(texSizeX[sliceX], texSizeY[sliceY]);
mVertices[v + 0].tex = texPos;
mVertices[v + 1].tex = texPos + Vector2f(0, texSize.y());
mVertices[v + 2].tex = texPos + Vector2f(texSize.x(), 0);
mVertices[v + 3].tex = mVertices[v + 2].tex;
mVertices[v + 4].tex = mVertices[v + 1].tex;
mVertices[v + 5].tex = texPos + texSize;
v += 6; v += 6;
} }
@ -99,6 +88,8 @@ void NinePatchComponent::buildVertices()
{ {
mVertices[i].pos.round(); mVertices[i].pos.round();
} }
updateColors();
} }
void NinePatchComponent::render(const Transform4x4f& parentTrans) void NinePatchComponent::render(const Transform4x4f& parentTrans)
@ -111,27 +102,7 @@ void NinePatchComponent::render(const Transform4x4f& parentTrans)
Renderer::setMatrix(trans); Renderer::setMatrix(trans);
mTexture->bind(); mTexture->bind();
Renderer::drawTriangleStrips(&mVertices[0], 6*9);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &mVertices[0].pos);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &mVertices[0].tex);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, mColors);
glDrawArrays(GL_TRIANGLES, 0, 6 * 9);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
} }
renderChildren(trans); renderChildren(trans);

View file

@ -2,9 +2,8 @@
#ifndef ES_CORE_COMPONENTS_NINE_PATCH_COMPONENT_H #ifndef ES_CORE_COMPONENTS_NINE_PATCH_COMPONENT_H
#define ES_CORE_COMPONENTS_NINE_PATCH_COMPONENT_H #define ES_CORE_COMPONENTS_NINE_PATCH_COMPONENT_H
#include "renderers/Renderer.h"
#include "GuiComponent.h" #include "GuiComponent.h"
#include "platform.h"
#include GLHEADER
class TextureResource; class TextureResource;
@ -45,14 +44,7 @@ private:
void buildVertices(); void buildVertices();
void updateColors(); void updateColors();
struct Vertex Renderer::Vertex* mVertices;
{
Vector2f pos;
Vector2f tex;
};
Vertex* mVertices;
GLubyte* mColors;
std::string mPath; std::string mPath;
Vector2f mCornerSize; Vector2f mCornerSize;

View file

@ -1,6 +1,7 @@
#include "components/ScrollableContainer.h" #include "components/ScrollableContainer.h"
#include "Renderer.h" #include "math/Vector2i.h"
#include "renderers/Renderer.h"
#define AUTO_SCROLL_RESET_DELAY 3000 // ms to reset to top after we reach the bottom #define AUTO_SCROLL_RESET_DELAY 3000 // ms to reset to top after we reach the bottom
#define AUTO_SCROLL_DELAY 1000 // ms to wait before we start to scroll #define AUTO_SCROLL_DELAY 1000 // ms to wait before we start to scroll

View file

@ -1,7 +1,6 @@
#include "components/SliderComponent.h" #include "components/SliderComponent.h"
#include "resources/Font.h" #include "resources/Font.h"
#include "Renderer.h"
#define MOVE_REPEAT_DELAY 500 #define MOVE_REPEAT_DELAY 500
#define MOVE_REPEAT_RATE 40 #define MOVE_REPEAT_RATE 40

View file

@ -1,7 +1,6 @@
#include "SwitchComponent.h" #include "SwitchComponent.h"
#include "resources/Font.h" #include "resources/Font.h"
#include "Renderer.h"
SwitchComponent::SwitchComponent(Window* window, bool state) : GuiComponent(window), mImage(window), mState(state) SwitchComponent::SwitchComponent(Window* window, bool state) : GuiComponent(window), mImage(window), mState(state)
{ {

View file

@ -2,7 +2,6 @@
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
#include "Log.h" #include "Log.h"
#include "Renderer.h"
#include "Settings.h" #include "Settings.h"
TextComponent::TextComponent(Window* window) : GuiComponent(window), TextComponent::TextComponent(Window* window) : GuiComponent(window),

View file

@ -2,7 +2,6 @@
#include "resources/Font.h" #include "resources/Font.h"
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
#include "Renderer.h"
#define TEXT_PADDING_HORIZ 10 #define TEXT_PADDING_HORIZ 10
#define TEXT_PADDING_VERT 2 #define TEXT_PADDING_VERT 2

View file

@ -3,7 +3,6 @@
#include "resources/ResourceManager.h" #include "resources/ResourceManager.h"
#include "utils/FileSystemUtil.h" #include "utils/FileSystemUtil.h"
#include "PowerSaver.h" #include "PowerSaver.h"
#include "Renderer.h"
#include "ThemeData.h" #include "ThemeData.h"
#include "Window.h" #include "Window.h"
#include <SDL_timer.h> #include <SDL_timer.h>

View file

@ -1,9 +1,9 @@
#ifdef _RPI_ #ifdef _RPI_
#include "components/VideoPlayerComponent.h" #include "components/VideoPlayerComponent.h"
#include "renderers/Renderer.h"
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
#include "AudioManager.h" #include "AudioManager.h"
#include "Renderer.h"
#include "Settings.h" #include "Settings.h"
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
@ -115,7 +115,7 @@ void VideoPlayerComponent::startVideo()
case 1: case 1:
{ {
const int x1 = (int)(Renderer::getScreenOffsetY() + Renderer::getScreenHeight() - y - mSize.y()); const int x1 = (int)(Renderer::getScreenWidth() - Renderer::getScreenOffsetY() - y - mSize.y());
const int y1 = (int)(Renderer::getScreenOffsetX() + x); const int y1 = (int)(Renderer::getScreenOffsetX() + x);
const int x2 = (int)(x1 + mSize.y()); const int x2 = (int)(x1 + mSize.y());
const int y2 = (int)(y1 + mSize.x()); const int y2 = (int)(y1 + mSize.x());
@ -125,8 +125,8 @@ void VideoPlayerComponent::startVideo()
case 2: case 2:
{ {
const int x1 = (int)(Renderer::getScreenOffsetX() + Renderer::getScreenWidth() - x - mSize.x()); const int x1 = (int)(Renderer::getScreenWidth() - Renderer::getScreenOffsetX() - x - mSize.x());
const int y1 = (int)(Renderer::getScreenOffsetY() + Renderer::getScreenHeight() - y - mSize.y()); const int y1 = (int)(Renderer::getScreenHeight() - Renderer::getScreenOffsetY() - y - mSize.y());
const int x2 = (int)(x1 + mSize.x()); const int x2 = (int)(x1 + mSize.x());
const int y2 = (int)(y1 + mSize.y()); const int y2 = (int)(y1 + mSize.y());
sprintf(buf1, "%d,%d,%d,%d", x1, y1, x2, y2); sprintf(buf1, "%d,%d,%d,%d", x1, y1, x2, y2);
@ -136,7 +136,7 @@ void VideoPlayerComponent::startVideo()
case 3: case 3:
{ {
const int x1 = (int)(Renderer::getScreenOffsetY() + y); const int x1 = (int)(Renderer::getScreenOffsetY() + y);
const int y1 = (int)(Renderer::getScreenOffsetX() + Renderer::getScreenWidth() - x - mSize.x()); const int y1 = (int)(Renderer::getScreenHeight() - Renderer::getScreenOffsetX() - x - mSize.x());
const int x2 = (int)(x1 + mSize.y()); const int x2 = (int)(x1 + mSize.y());
const int y2 = (int)(y1 + mSize.x()); const int y2 = (int)(y1 + mSize.x());
sprintf(buf1, "%d,%d,%d,%d", x1, y1, x2, y2); sprintf(buf1, "%d,%d,%d,%d", x1, y1, x2, y2);

View file

@ -1,9 +1,9 @@
#include "components/VideoVlcComponent.h" #include "components/VideoVlcComponent.h"
#include "renderers/Renderer.h"
#include "resources/TextureResource.h" #include "resources/TextureResource.h"
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
#include "PowerSaver.h" #include "PowerSaver.h"
#include "Renderer.h"
#include "Settings.h" #include "Settings.h"
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <SDL_mutex.h> #include <SDL_mutex.h>
@ -132,8 +132,6 @@ void VideoVlcComponent::resize()
void VideoVlcComponent::render(const Transform4x4f& parentTrans) void VideoVlcComponent::render(const Transform4x4f& parentTrans)
{ {
VideoComponent::render(parentTrans); VideoComponent::render(parentTrans);
float x, y;
Transform4x4f trans = parentTrans * getTransform(); Transform4x4f trans = parentTrans * getTransform();
GuiComponent::renderChildren(trans); GuiComponent::renderChildren(trans);
@ -141,73 +139,24 @@ void VideoVlcComponent::render(const Transform4x4f& parentTrans)
if (mIsPlaying && mContext.valid) if (mIsPlaying && mContext.valid)
{ {
float tex_offs_x = 0.0f; const unsigned int fadeIn = (unsigned int)(Math::clamp(0.0f, mFadeIn, 1.0f) * 255.0f);
float tex_offs_y = 0.0f; const unsigned int color = Renderer::convertColor((fadeIn << 24) | (fadeIn << 16) | (fadeIn << 8) | 255);
float x2; Renderer::Vertex vertices[4];
float y2;
x = 0.0; vertices[0] = { { 0.0f , 0.0f }, { 0.0f, 0.0f }, color };
y = 0.0; vertices[1] = { { 0.0f , mSize.y() }, { 0.0f, 1.0f }, color };
x2 = mSize.x(); vertices[2] = { { mSize.x(), 0.0f }, { 1.0f, 0.0f }, color };
y2 = mSize.y(); vertices[3] = { { mSize.x(), mSize.y() }, { 1.0f, 1.0f }, color };
// Define a structure to contain the data for each vertex
struct Vertex
{
Vector2f pos;
Vector2f tex;
Vector4f colour;
} vertices[6];
// We need two triangles to cover the rectangular area
vertices[0].pos[0] = x; vertices[0].pos[1] = y;
vertices[1].pos[0] = x; vertices[1].pos[1] = y2;
vertices[2].pos[0] = x2; vertices[2].pos[1] = y;
vertices[3].pos[0] = x2; vertices[3].pos[1] = y;
vertices[4].pos[0] = x; vertices[4].pos[1] = y2;
vertices[5].pos[0] = x2; vertices[5].pos[1] = y2;
// Texture coordinates
vertices[0].tex[0] = -tex_offs_x; vertices[0].tex[1] = -tex_offs_y;
vertices[1].tex[0] = -tex_offs_x; vertices[1].tex[1] = 1.0f + tex_offs_y;
vertices[2].tex[0] = 1.0f + tex_offs_x; vertices[2].tex[1] = -tex_offs_y;
vertices[3].tex[0] = 1.0f + tex_offs_x; vertices[3].tex[1] = -tex_offs_y;
vertices[4].tex[0] = -tex_offs_x; vertices[4].tex[1] = 1.0f + tex_offs_y;
vertices[5].tex[0] = 1.0f + tex_offs_x; vertices[5].tex[1] = 1.0f + tex_offs_y;
// Colours - use this to fade the video in and out
for (int i = 0; i < (4 * 6); ++i) {
if ((i%4) < 3)
vertices[i / 4].colour[i % 4] = mFadeIn;
else
vertices[i / 4].colour[i % 4] = 1.0f;
}
glEnable(GL_TEXTURE_2D);
// Build a texture for the video frame // Build a texture for the video frame
mTexture->initFromPixels((unsigned char*)mContext.surface->pixels, mContext.surface->w, mContext.surface->h); mTexture->initFromPixels((unsigned char*)mContext.surface->pixels, mContext.surface->w, mContext.surface->h);
mTexture->bind(); mTexture->bind();
// Render it // Render it
glEnableClientState(GL_COLOR_ARRAY); Renderer::drawTriangleStrips(&vertices[0], 4);
glEnableClientState(GL_VERTEX_ARRAY); }
glEnableClientState(GL_TEXTURE_COORD_ARRAY); else
{
glColorPointer(4, GL_FLOAT, sizeof(Vertex), &vertices[0].colour);
glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].pos);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].tex);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisable(GL_TEXTURE_2D);
} else {
VideoComponent::renderSnapshot(parentTrans); VideoComponent::renderSnapshot(parentTrans);
} }
} }

View file

@ -6,7 +6,6 @@
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
#include "InputManager.h" #include "InputManager.h"
#include "PowerSaver.h" #include "PowerSaver.h"
#include "Renderer.h"
#include "Window.h" #include "Window.h"
#define HOLD_TIME 1000 #define HOLD_TIME 1000

View file

@ -4,23 +4,11 @@
#include <string> #include <string>
//the Makefile defines one of these:
//#define USE_OPENGL_ES
//#define USE_OPENGL_DESKTOP
#ifdef USE_OPENGL_ES
#define GLHEADER <GLES/gl.h>
#endif
#ifdef USE_OPENGL_DESKTOP
//why the hell this naming inconsistency exists is well beyond me //why the hell this naming inconsistency exists is well beyond me
#ifdef WIN32 #ifdef WIN32
#define sleep Sleep #define sleep Sleep
#endif #endif
#define GLHEADER <SDL_opengl.h>
#endif
int runShutdownCommand(); // shut down the system (returns 0 if successful) int runShutdownCommand(); // shut down the system (returns 0 if successful)
int runRestartCommand(); // restart the system (returns 0 if successful) int runRestartCommand(); // restart the system (returns 0 if successful)
int runSystemCommand(const std::string& cmd_utf8); // run a utf-8 encoded in the shell (requires wstring conversion on Windows) int runSystemCommand(const std::string& cmd_utf8); // run a utf-8 encoded in the shell (requires wstring conversion on Windows)

View file

@ -0,0 +1,269 @@
#include "renderers/Renderer.h"
#include "math/Transform4x4f.h"
#include "math/Vector2i.h"
#include "resources/ResourceManager.h"
#include "ImageIO.h"
#include "Log.h"
#include "Settings.h"
#include <SDL.h>
#include <stack>
namespace Renderer
{
static std::stack<Rect> clipStack;
static SDL_Window* sdlWindow = nullptr;
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 int screenRotate = 0;
static bool initialCursorState = 1;
static void setIcon()
{
size_t width = 0;
size_t height = 0;
ResourceData resData = ResourceManager::getInstance()->getFileData(":/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 SDL_BYTEORDER == SDL_BIG_ENDIAN
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;
#endif
// try creating SDL surface from logo data
SDL_Surface* logoSurface = SDL_CreateRGBSurfaceFrom((void*)rawData.data(), (int)width, (int)height, 32, (int)(width * 4), rmask, gmask, bmask, amask);
if(logoSurface != nullptr)
{
SDL_SetWindowIcon(sdlWindow, logoSurface);
SDL_FreeSurface(logoSurface);
}
}
} // setIcon
static bool createWindow()
{
LOG(LogInfo) << "Creating window...";
if(SDL_Init(SDL_INIT_VIDEO) != 0)
{
LOG(LogError) << "Error initializing SDL!\n " << SDL_GetError();
return false;
}
initialCursorState = (SDL_ShowCursor(0) != 0);
SDL_DisplayMode dispMode;
SDL_GetDesktopDisplayMode(0, &dispMode);
windowWidth = Settings::getInstance()->getInt("WindowWidth") ? Settings::getInstance()->getInt("WindowWidth") : dispMode.w;
windowHeight = Settings::getInstance()->getInt("WindowHeight") ? Settings::getInstance()->getInt("WindowHeight") : dispMode.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;
screenRotate = Settings::getInstance()->getInt("ScreenRotate") ? Settings::getInstance()->getInt("ScreenRotate") : 0;
setupWindow();
unsigned int windowFlags = (Settings::getInstance()->getBool("Windowed") ? 0 : (Settings::getInstance()->getBool("FullscreenBorderless") ? SDL_WINDOW_BORDERLESS : SDL_WINDOW_FULLSCREEN)) | getWindowFlags();
if((sdlWindow = SDL_CreateWindow("EmulationStation", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, windowFlags)) == nullptr)
{
LOG(LogError) << "Error creating SDL window!\n\t" << SDL_GetError();
return false;
}
LOG(LogInfo) << "Created window successfully.";
createContext();
setIcon();
setSwapInterval();
return true;
} // createWindow
static void destroyWindow()
{
destroyContext();
SDL_DestroyWindow(sdlWindow);
sdlWindow = nullptr;
SDL_ShowCursor(initialCursorState);
SDL_Quit();
} // destroyWindow
bool init()
{
if(!createWindow())
return false;
Transform4x4f projection = Transform4x4f::Identity();
Rect viewport = Rect(0, 0, 0, 0);
switch(screenRotate)
{
case 0:
{
viewport.x = screenOffsetX;
viewport.y = screenOffsetY;
viewport.w = screenWidth;
viewport.h = screenHeight;
projection.orthoProjection(0, screenWidth, screenHeight, 0, -1.0, 1.0);
}
break;
case 1:
{
viewport.x = windowWidth - screenOffsetY - screenHeight;
viewport.y = screenOffsetX;
viewport.w = screenHeight;
viewport.h = screenWidth;
projection.orthoProjection(0, screenHeight, screenWidth, 0, -1.0, 1.0);
projection.rotate((float)ES_DEG_TO_RAD(90), {0, 0, 1});
projection.translate({0, screenHeight * -1.0f, 0});
}
break;
case 2:
{
viewport.x = windowWidth - screenOffsetX - screenWidth;
viewport.y = windowHeight - screenOffsetY - screenHeight;
viewport.w = screenWidth;
viewport.h = screenHeight;
projection.orthoProjection(0, screenWidth, screenHeight, 0, -1.0, 1.0);
projection.rotate((float)ES_DEG_TO_RAD(180), {0, 0, 1});
projection.translate({screenWidth * -1.0f, screenHeight * -1.0f, 0});
}
break;
case 3:
{
viewport.x = screenOffsetY;
viewport.y = windowHeight - screenOffsetX - screenWidth;
viewport.w = screenHeight;
viewport.h = screenWidth;
projection.orthoProjection(0, screenHeight, screenWidth, 0, -1.0, 1.0);
projection.rotate((float)ES_DEG_TO_RAD(270), {0, 0, 1});
projection.translate({screenWidth * -1.0f, 0, 0});
}
break;
}
setViewport(viewport);
setProjection(projection);
swapBuffers();
return true;
} // init
void deinit()
{
destroyWindow();
} // deinit
void pushClipRect(const Vector2i& _pos, const Vector2i& _size)
{
Rect box(_pos.x(), _pos.y(), _size.x(), _size.y());
if(box.w == 0) box.w = screenWidth - box.x;
if(box.h == 0) box.h = screenHeight - box.y;
switch(screenRotate)
{
case 0: { box = Rect(screenOffsetX + box.x, screenOffsetY + box.y, box.w, box.h); } break;
case 1: { box = Rect(windowWidth - screenOffsetY - box.y - box.h, screenOffsetX + box.x, box.h, box.w); } break;
case 2: { box = Rect(windowWidth - screenOffsetX - box.x - box.w, windowHeight - screenOffsetY - box.y - box.h, box.w, box.h); } break;
case 3: { box = Rect(screenOffsetY + box.y, windowHeight - screenOffsetX - box.x - box.w, box.h, box.w); } break;
}
// 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(box.w < 0) box.w = 0;
if(box.h < 0) box.h = 0;
clipStack.push(box);
setScissor(box);
} // pushClipRect
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());
} // popClipRect
void drawRect(const float _x, const float _y, const float _w, const float _h, const unsigned int _color, const Blend::Factor _srcBlendFactor, const Blend::Factor _dstBlendFactor)
{
drawRect((int)Math::round(_x), (int)Math::round(_y), (int)Math::round(_w), (int)Math::round(_h), _color, _srcBlendFactor, _dstBlendFactor);
} // drawRect
void drawRect(const int _x, const int _y, const int _w, const int _h, const unsigned int _color, const Blend::Factor _srcBlendFactor, const Blend::Factor _dstBlendFactor)
{
const unsigned int color = convertColor(_color);
Vertex vertices[4];
vertices[0] = { { (float)(_x ), (float)(_y ) }, { 0.0f, 0.0f }, color };
vertices[1] = { { (float)(_x ), (float)(_y + _h) }, { 0.0f, 0.0f }, color };
vertices[2] = { { (float)(_x + _w), (float)(_y ) }, { 0.0f, 0.0f }, color };
vertices[3] = { { (float)(_x + _w), (float)(_y + _h) }, { 0.0f, 0.0f }, color };
bindTexture(0);
drawTriangleStrips(vertices, 4, _srcBlendFactor, _dstBlendFactor);
} // drawRect
SDL_Window* getSDLWindow() { return sdlWindow; }
int getWindowWidth() { return windowWidth; }
int getWindowHeight() { return windowHeight; }
int getScreenWidth() { return screenWidth; }
int getScreenHeight() { return screenHeight; }
int getScreenOffsetX() { return screenOffsetX; }
int getScreenOffsetY() { return screenOffsetY; }
int getScreenRotate() { return screenRotate; }
} // Renderer::

View file

@ -0,0 +1,102 @@
#pragma once
#ifndef ES_CORE_RENDERER_RENDERER_H
#define ES_CORE_RENDERER_RENDERER_H
#include "math/Vector2f.h"
class Transform4x4f;
class Vector2i;
struct SDL_Window;
namespace Renderer
{
namespace Blend
{
enum Factor
{
ZERO = 0,
ONE = 1,
SRC_COLOR = 2,
ONE_MINUS_SRC_COLOR = 3,
SRC_ALPHA = 4,
ONE_MINUS_SRC_ALPHA = 5,
DST_COLOR = 6,
ONE_MINUS_DST_COLOR = 7,
DST_ALPHA = 8,
ONE_MINUS_DST_ALPHA = 9
}; // Factor
} // Blend::
namespace Texture
{
enum Type
{
RGBA = 0,
ALPHA = 1
}; // Type
} // Texture::
struct Rect
{
Rect(const int _x, const int _y, const int _w, const int _h) : x(_x), y(_y), w(_w), h(_h) { }
int x;
int y;
int w;
int h;
}; // Rect
struct Vertex
{
Vertex() { }
Vertex(const Vector2f& _pos, const Vector2f& _tex, const unsigned int _col) : pos(_pos), tex(_tex), col(_col) { }
Vector2f pos;
Vector2f tex;
unsigned int col;
}; // Vertex
bool init ();
void deinit ();
void pushClipRect (const Vector2i& _pos, const Vector2i& _size);
void popClipRect ();
void drawRect (const float _x, const float _y, const float _w, const float _h, const unsigned int _color, const Blend::Factor _srcBlendFactor = Blend::SRC_ALPHA, const Blend::Factor _dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA);
void drawRect (const int _x, const int _y, const int _w, const int _h, const unsigned int _color, const Blend::Factor _srcBlendFactor = Blend::SRC_ALPHA, const Blend::Factor _dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA);
SDL_Window* getSDLWindow ();
int getWindowWidth ();
int getWindowHeight ();
int getScreenWidth ();
int getScreenHeight ();
int getScreenOffsetX();
int getScreenOffsetY();
int getScreenRotate ();
// API specific
unsigned int convertColor (const unsigned int _color);
unsigned int getWindowFlags ();
void setupWindow ();
void createContext ();
void destroyContext ();
unsigned int createTexture (const Texture::Type _type, const bool _linear, const bool _repeat, 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 _y, const unsigned int _width, const unsigned int _height, void* _data);
void bindTexture (const unsigned int _texture);
void drawLines (const Vertex* _vertices, const unsigned int _numVertices, const Blend::Factor _srcBlendFactor = Blend::SRC_ALPHA, const Blend::Factor _dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA);
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 setProjection (const Transform4x4f& _projection);
void setMatrix (const Transform4x4f& _matrix);
void setViewport (const Rect& _viewport);
void setScissor (const Rect& _scissor);
void setSwapInterval ();
void swapBuffers ();
} // Renderer::
#endif // ES_CORE_RENDERER_RENDERER_H

View file

@ -0,0 +1,251 @@
#if defined(USE_OPENGL_21)
#include "renderers/Renderer.h"
#include "Log.h"
#include "Settings.h"
#include <SDL_opengl.h>
#include <SDL.h>
namespace Renderer
{
static SDL_GLContext sdlContext = nullptr;
static GLenum convertBlendFactor(const Blend::Factor _blendFactor)
{
switch(_blendFactor)
{
case Blend::ZERO: { return GL_ZERO; } break;
case Blend::ONE: { return GL_ONE; } break;
case Blend::SRC_COLOR: { return GL_SRC_COLOR; } break;
case Blend::ONE_MINUS_SRC_COLOR: { return GL_ONE_MINUS_SRC_COLOR; } break;
case Blend::SRC_ALPHA: { return GL_SRC_ALPHA; } break;
case Blend::ONE_MINUS_SRC_ALPHA: { return GL_ONE_MINUS_SRC_ALPHA; } break;
case Blend::DST_COLOR: { return GL_DST_COLOR; } break;
case Blend::ONE_MINUS_DST_COLOR: { return GL_ONE_MINUS_DST_COLOR; } break;
case Blend::DST_ALPHA: { return GL_DST_ALPHA; } break;
case Blend::ONE_MINUS_DST_ALPHA: { return GL_ONE_MINUS_DST_ALPHA; } break;
default: { return GL_ZERO; }
}
} // convertBlendFactor
static GLenum convertTextureType(const Texture::Type _type)
{
switch(_type)
{
case Texture::RGBA: { return GL_RGBA; } break;
case Texture::ALPHA: { return GL_ALPHA; } break;
default: { return GL_ZERO; }
}
} // convertTextureType
unsigned int convertColor(const unsigned int _color)
{
// convert from rgba to abgr
unsigned char r = ((_color & 0xff000000) >> 24) & 255;
unsigned char g = ((_color & 0x00ff0000) >> 16) & 255;
unsigned char b = ((_color & 0x0000ff00) >> 8) & 255;
unsigned char a = ((_color & 0x000000ff) ) & 255;
return ((a << 24) | (b << 16) | (g << 8) | (r));
} // convertColor
unsigned int getWindowFlags()
{
return SDL_WINDOW_OPENGL;
} // getWindowFlags
void setupWindow()
{
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
} // setupWindow
void createContext()
{
sdlContext = SDL_GL_CreateContext(getSDLWindow());
SDL_GL_MakeCurrent(getSDLWindow(), sdlContext);
glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
std::string glExts = (const char*)glGetString(GL_EXTENSIONS);
LOG(LogInfo) << "Checking available OpenGL extensions...";
LOG(LogInfo) << " ARB_texture_non_power_of_two: " << (glExts.find("ARB_texture_non_power_of_two") != std::string::npos ? "ok" : "MISSING");
} // createContext
void destroyContext()
{
SDL_GL_DeleteContext(sdlContext);
sdlContext = nullptr;
} // destroyContext
unsigned int createTexture(const Texture::Type _type, const bool _linear, const bool _repeat, const unsigned int _width, const unsigned int _height, void* _data)
{
const GLenum type = convertTextureType(_type);
unsigned int texture;
glGenTextures(1, &texture);
bindTexture(texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _linear ? GL_LINEAR : GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _linear ? GL_LINEAR : GL_NEAREST);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, type, _width, _height, 0, type, GL_UNSIGNED_BYTE, _data);
return texture;
} // createTexture
void destroyTexture(const unsigned int _texture)
{
glDeleteTextures(1, &_texture);
} // destroyTexture
void updateTexture(const unsigned int _texture, const Texture::Type _type, const unsigned int _x, const unsigned _y, const unsigned int _width, const unsigned int _height, void* _data)
{
bindTexture(_texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, _x, _y, _width, _height, convertTextureType(_type), GL_UNSIGNED_BYTE, _data);
bindTexture(0);
} // updateTexture
void bindTexture(const unsigned int _texture)
{
glBindTexture(GL_TEXTURE_2D, _texture);
if(_texture == 0) glDisable(GL_TEXTURE_2D);
else glEnable(GL_TEXTURE_2D);
} // bindTexture
void drawLines(const Vertex* _vertices, const unsigned int _numVertices, const Blend::Factor _srcBlendFactor, const Blend::Factor _dstBlendFactor)
{
glEnable(GL_BLEND);
glBlendFunc(convertBlendFactor(_srcBlendFactor), convertBlendFactor(_dstBlendFactor));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer( 2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex);
glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(Vertex), &_vertices[0].col);
glDrawArrays(GL_LINES, 0, _numVertices);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_BLEND);
} // drawLines
void drawTriangleStrips(const Vertex* _vertices, const unsigned int _numVertices, const Blend::Factor _srcBlendFactor, const Blend::Factor _dstBlendFactor)
{
glEnable(GL_BLEND);
glBlendFunc(convertBlendFactor(_srcBlendFactor), convertBlendFactor(_dstBlendFactor));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer( 2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex);
glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(Vertex), &_vertices[0].col);
glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_BLEND);
} // drawTriangleStrips
void setProjection(const Transform4x4f& _projection)
{
glMatrixMode(GL_PROJECTION);
glLoadMatrixf((GLfloat*)&_projection);
} // setProjection
void setMatrix(const Transform4x4f& _matrix)
{
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf((GLfloat*)&_matrix);
} // setMatrix
void setViewport(const Rect& _viewport)
{
// glViewport starts at the bottom left of the window
glViewport( _viewport.x, getWindowHeight() - _viewport.y - _viewport.h, _viewport.w, _viewport.h);
} // setViewport
void setScissor(const Rect& _scissor)
{
if((_scissor.x == 0) && (_scissor.y == 0) && (_scissor.w == 0) && (_scissor.h == 0))
{
glDisable(GL_SCISSOR_TEST);
}
else
{
// glScissor starts at the bottom left of the window
glScissor(_scissor.x, getWindowHeight() - _scissor.y - _scissor.h, _scissor.w, _scissor.h);
glEnable(GL_SCISSOR_TEST);
}
} // setScissor
void setSwapInterval()
{
// vsync
if(Settings::getInstance()->getBool("VSync"))
{
// SDL_GL_SetSwapInterval(0) for immediate updates (no vsync, default),
// 1 for updates synchronized with the vertical retrace,
// or -1 for late swap tearing.
// SDL_GL_SetSwapInterval returns 0 on success, -1 on error.
// if vsync is requested, try normal vsync; if that doesn't work, try late swap tearing
// if that doesn't work, report an error
if(SDL_GL_SetSwapInterval(1) != 0 && SDL_GL_SetSwapInterval(-1) != 0)
LOG(LogWarning) << "Tried to enable vsync, but failed! (" << SDL_GetError() << ")";
}
else
SDL_GL_SetSwapInterval(0);
} // setSwapInterval
void swapBuffers()
{
SDL_GL_SwapWindow(getSDLWindow());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
} // swapBuffers
} // Renderer::
#endif // USE_OPENGL_21

View file

@ -0,0 +1,251 @@
#if defined(USE_OPENGLES_10)
#include "renderers/Renderer.h"
#include "Log.h"
#include "Settings.h"
#include <GLES/gl.h>
#include <SDL.h>
namespace Renderer
{
static SDL_GLContext sdlContext = nullptr;
static GLenum convertBlendFactor(const Blend::Factor _blendFactor)
{
switch(_blendFactor)
{
case Blend::ZERO: { return GL_ZERO; } break;
case Blend::ONE: { return GL_ONE; } break;
case Blend::SRC_COLOR: { return GL_SRC_COLOR; } break;
case Blend::ONE_MINUS_SRC_COLOR: { return GL_ONE_MINUS_SRC_COLOR; } break;
case Blend::SRC_ALPHA: { return GL_SRC_ALPHA; } break;
case Blend::ONE_MINUS_SRC_ALPHA: { return GL_ONE_MINUS_SRC_ALPHA; } break;
case Blend::DST_COLOR: { return GL_DST_COLOR; } break;
case Blend::ONE_MINUS_DST_COLOR: { return GL_ONE_MINUS_DST_COLOR; } break;
case Blend::DST_ALPHA: { return GL_DST_ALPHA; } break;
case Blend::ONE_MINUS_DST_ALPHA: { return GL_ONE_MINUS_DST_ALPHA; } break;
default: { return GL_ZERO; }
}
} // convertBlendFactor
static GLenum convertTextureType(const Texture::Type _type)
{
switch(_type)
{
case Texture::RGBA: { return GL_RGBA; } break;
case Texture::ALPHA: { return GL_ALPHA; } break;
default: { return GL_ZERO; }
}
} // convertTextureType
unsigned int convertColor(const unsigned int _color)
{
// convert from rgba to abgr
unsigned char r = ((_color & 0xff000000) >> 24) & 255;
unsigned char g = ((_color & 0x00ff0000) >> 16) & 255;
unsigned char b = ((_color & 0x0000ff00) >> 8) & 255;
unsigned char a = ((_color & 0x000000ff) ) & 255;
return ((a << 24) | (b << 16) | (g << 8) | (r));
} // convertColor
unsigned int getWindowFlags()
{
return SDL_WINDOW_OPENGL;
} // getWindowFlags
void setupWindow()
{
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 0);
} // setupWindow
void createContext()
{
sdlContext = SDL_GL_CreateContext(getSDLWindow());
SDL_GL_MakeCurrent(getSDLWindow(), sdlContext);
glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
std::string glExts = (const char*)glGetString(GL_EXTENSIONS);
LOG(LogInfo) << "Checking available OpenGL extensions...";
LOG(LogInfo) << " ARB_texture_non_power_of_two: " << (glExts.find("ARB_texture_non_power_of_two") != std::string::npos ? "ok" : "MISSING");
} // createContext
void destroyContext()
{
SDL_GL_DeleteContext(sdlContext);
sdlContext = nullptr;
} // destroyContext
unsigned int createTexture(const Texture::Type _type, const bool _linear, const bool _repeat, const unsigned int _width, const unsigned int _height, void* _data)
{
const GLenum type = convertTextureType(_type);
unsigned int texture;
glGenTextures(1, &texture);
bindTexture(texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _linear ? GL_LINEAR : GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _linear ? GL_LINEAR : GL_NEAREST);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, type, _width, _height, 0, type, GL_UNSIGNED_BYTE, _data);
return texture;
} // createTexture
void destroyTexture(const unsigned int _texture)
{
glDeleteTextures(1, &_texture);
} // destroyTexture
void updateTexture(const unsigned int _texture, const Texture::Type _type, const unsigned int _x, const unsigned _y, const unsigned int _width, const unsigned int _height, void* _data)
{
bindTexture(_texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, _x, _y, _width, _height, convertTextureType(_type), GL_UNSIGNED_BYTE, _data);
bindTexture(0);
} // updateTexture
void bindTexture(const unsigned int _texture)
{
glBindTexture(GL_TEXTURE_2D, _texture);
if(_texture == 0) glDisable(GL_TEXTURE_2D);
else glEnable(GL_TEXTURE_2D);
} // bindTexture
void drawLines(const Vertex* _vertices, const unsigned int _numVertices, const Blend::Factor _srcBlendFactor, const Blend::Factor _dstBlendFactor)
{
glEnable(GL_BLEND);
glBlendFunc(convertBlendFactor(_srcBlendFactor), convertBlendFactor(_dstBlendFactor));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer( 2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex);
glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(Vertex), &_vertices[0].col);
glDrawArrays(GL_LINES, 0, _numVertices);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_BLEND);
} // drawLines
void drawTriangleStrips(const Vertex* _vertices, const unsigned int _numVertices, const Blend::Factor _srcBlendFactor, const Blend::Factor _dstBlendFactor)
{
glEnable(GL_BLEND);
glBlendFunc(convertBlendFactor(_srcBlendFactor), convertBlendFactor(_dstBlendFactor));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer( 2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex);
glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(Vertex), &_vertices[0].col);
glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_BLEND);
} // drawTriangleStrips
void setProjection(const Transform4x4f& _projection)
{
glMatrixMode(GL_PROJECTION);
glLoadMatrixf((GLfloat*)&_projection);
} // setProjection
void setMatrix(const Transform4x4f& _matrix)
{
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf((GLfloat*)&_matrix);
} // setMatrix
void setViewport(const Rect& _viewport)
{
// glViewport starts at the bottom left of the window
glViewport( _viewport.x, getWindowHeight() - _viewport.y - _viewport.h, _viewport.w, _viewport.h);
} // setViewport
void setScissor(const Rect& _scissor)
{
if((_scissor.x == 0) && (_scissor.y == 0) && (_scissor.w == 0) && (_scissor.h == 0))
{
glDisable(GL_SCISSOR_TEST);
}
else
{
// glScissor starts at the bottom left of the window
glScissor(_scissor.x, getWindowHeight() - _scissor.y - _scissor.h, _scissor.w, _scissor.h);
glEnable(GL_SCISSOR_TEST);
}
} // setScissor
void setSwapInterval()
{
// vsync
if(Settings::getInstance()->getBool("VSync"))
{
// SDL_GL_SetSwapInterval(0) for immediate updates (no vsync, default),
// 1 for updates synchronized with the vertical retrace,
// or -1 for late swap tearing.
// SDL_GL_SetSwapInterval returns 0 on success, -1 on error.
// if vsync is requested, try normal vsync; if that doesn't work, try late swap tearing
// if that doesn't work, report an error
if(SDL_GL_SetSwapInterval(1) != 0 && SDL_GL_SetSwapInterval(-1) != 0)
LOG(LogWarning) << "Tried to enable vsync, but failed! (" << SDL_GetError() << ")";
}
else
SDL_GL_SetSwapInterval(0);
} // setSwapInterval
void swapBuffers()
{
SDL_GL_SwapWindow(getSDLWindow());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
} // swapBuffers
} // Renderer::
#endif // USE_OPENGLES_10

View file

@ -1,9 +1,13 @@
#include "resources/Font.h" #include "resources/Font.h"
#include "renderers/Renderer.h"
#include "utils/FileSystemUtil.h" #include "utils/FileSystemUtil.h"
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
#include "Log.h" #include "Log.h"
#include "Renderer.h"
#ifdef WIN32
#include <Windows.h>
#endif
FT_Library Font::sLibrary = NULL; FT_Library Font::sLibrary = NULL;
@ -171,27 +175,14 @@ bool Font::FontTexture::findEmpty(const Vector2i& size, Vector2i& cursor_out)
void Font::FontTexture::initTexture() void Font::FontTexture::initTexture()
{ {
assert(textureId == 0); assert(textureId == 0);
textureId = Renderer::createTexture(Renderer::Texture::ALPHA, false, false, textureSize.x(), textureSize.y(), nullptr);
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, textureSize.x(), textureSize.y(), 0, GL_ALPHA, GL_UNSIGNED_BYTE, NULL);
} }
void Font::FontTexture::deinitTexture() void Font::FontTexture::deinitTexture()
{ {
if(textureId != 0) if(textureId != 0)
{ {
glDeleteTextures(1, &textureId); Renderer::destroyTexture(textureId);
textureId = 0; textureId = 0;
} }
} }
@ -355,9 +346,7 @@ Font::Glyph* Font::getGlyph(unsigned int id)
glyph.bearing = Vector2f((float)g->metrics.horiBearingX / 64.0f, (float)g->metrics.horiBearingY / 64.0f); glyph.bearing = Vector2f((float)g->metrics.horiBearingX / 64.0f, (float)g->metrics.horiBearingY / 64.0f);
// upload glyph bitmap to texture // upload glyph bitmap to texture
glBindTexture(GL_TEXTURE_2D, tex->textureId); Renderer::updateTexture(tex->textureId, Renderer::Texture::ALPHA, cursor.x(), cursor.y(), glyphSize.x(), glyphSize.y(), g->bitmap.buffer);
glTexSubImage2D(GL_TEXTURE_2D, 0, cursor.x(), cursor.y(), glyphSize.x(), glyphSize.y(), GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
glBindTexture(GL_TEXTURE_2D, 0);
// update max glyph height // update max glyph height
if(glyphSize.y() > mMaxGlyphHeight) if(glyphSize.y() > mMaxGlyphHeight)
@ -392,11 +381,8 @@ void Font::rebuildTextures()
Vector2i glyphSize((int)(it->second.texSize.x() * tex->textureSize.x()), (int)(it->second.texSize.y() * tex->textureSize.y())); Vector2i glyphSize((int)(it->second.texSize.x() * tex->textureSize.x()), (int)(it->second.texSize.y() * tex->textureSize.y()));
// upload to texture // upload to texture
glBindTexture(GL_TEXTURE_2D, tex->textureId); Renderer::updateTexture(tex->textureId, Renderer::Texture::ALPHA, cursor.x(), cursor.y(), glyphSize.x(), glyphSize.y(), glyphSlot->bitmap.buffer);
glTexSubImage2D(GL_TEXTURE_2D, 0, cursor.x(), cursor.y(), glyphSize.x(), glyphSize.y(), GL_ALPHA, GL_UNSIGNED_BYTE, glyphSlot->bitmap.buffer);
} }
glBindTexture(GL_TEXTURE_2D, 0);
} }
void Font::renderTextCache(TextCache* cache) void Font::renderTextCache(TextCache* cache)
@ -413,27 +399,8 @@ void Font::renderTextCache(TextCache* cache)
auto vertexList = *it; auto vertexList = *it;
glBindTexture(GL_TEXTURE_2D, *it->textureIdPtr); Renderer::bindTexture(*it->textureIdPtr);
glEnable(GL_TEXTURE_2D); Renderer::drawTriangleStrips(&it->verts[0], it->verts.size());
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(TextCache::Vertex), &it->verts[0].pos);
glTexCoordPointer(2, GL_FLOAT, sizeof(TextCache::Vertex), &it->verts[0].tex);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, it->colors.data());
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)(it->verts.size()));
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
} }
} }
@ -605,7 +572,7 @@ TextCache* Font::buildTextCache(const std::string& text, Vector2f offset, unsign
float y = offset[1] + (yBot + yTop)/2.0f; float y = offset[1] + (yBot + yTop)/2.0f;
// vertices by texture // vertices by texture
std::map< FontTexture*, std::vector<TextCache::Vertex> > vertMap; std::map< FontTexture*, std::vector<Renderer::Vertex> > vertMap;
size_t cursor = 0; size_t cursor = 0;
while(cursor < text.length()) while(cursor < text.length())
@ -628,37 +595,23 @@ TextCache* Font::buildTextCache(const std::string& text, Vector2f offset, unsign
if(glyph == NULL) if(glyph == NULL)
continue; continue;
std::vector<TextCache::Vertex>& verts = vertMap[glyph->texture]; std::vector<Renderer::Vertex>& verts = vertMap[glyph->texture];
size_t oldVertSize = verts.size(); size_t oldVertSize = verts.size();
verts.resize(oldVertSize + 6); verts.resize(oldVertSize + 6);
TextCache::Vertex* tri = verts.data() + oldVertSize; Renderer::Vertex* vertices = verts.data() + oldVertSize;
const float glyphStartX = x + glyph->bearing.x(); const float glyphStartX = x + glyph->bearing.x();
const Vector2i& textureSize = glyph->texture->textureSize; const Vector2i& textureSize = glyph->texture->textureSize;
const unsigned int convertedColor = Renderer::convertColor(color);
// triangle 1 vertices[1] = { { Math::round(glyphStartX ), Math::round(y - glyph->bearing.y() ) }, { glyph->texPos.x(), glyph->texPos.y() }, convertedColor };
// round to fix some weird "cut off" text bugs vertices[2] = { { Math::round(glyphStartX ), Math::round(y - glyph->bearing.y() + (glyph->texSize.y() * textureSize.y())) }, { glyph->texPos.x(), glyph->texPos.y() + glyph->texSize.y() }, convertedColor };
tri[0].pos = Vector2f(Math::round(glyphStartX), Math::round(y + (glyph->texSize.y() * textureSize.y() - glyph->bearing.y()))); vertices[3] = { { Math::round(glyphStartX + glyph->texSize.x() * textureSize.x()), Math::round(y - glyph->bearing.y() ) }, { glyph->texPos.x() + glyph->texSize.x(), glyph->texPos.y() }, convertedColor };
tri[1].pos = Vector2f(Math::round(glyphStartX + glyph->texSize.x() * textureSize.x()), Math::round(y - glyph->bearing.y())); vertices[4] = { { Math::round(glyphStartX + glyph->texSize.x() * textureSize.x()), Math::round(y - glyph->bearing.y() + (glyph->texSize.y() * textureSize.y())) }, { glyph->texPos.x() + glyph->texSize.x(), glyph->texPos.y() + glyph->texSize.y() }, convertedColor };
tri[2].pos = Vector2f(tri[0].pos.x(), tri[1].pos.y());
//tri[0].tex = Vector2f(0, 0); // make duplicates of first and last vertex so this can be rendered as a triangle strip
//tri[0].tex = Vector2f(1, 1); vertices[0] = vertices[1];
//tri[0].tex = Vector2f(0, 1); vertices[5] = vertices[4];
tri[0].tex = Vector2f(glyph->texPos.x(), glyph->texPos.y() + glyph->texSize.y());
tri[1].tex = Vector2f(glyph->texPos.x() + glyph->texSize.x(), glyph->texPos.y());
tri[2].tex = Vector2f(tri[0].tex.x(), tri[1].tex.y());
// triangle 2
tri[3].pos = tri[0].pos;
tri[4].pos = tri[1].pos;
tri[5].pos = Vector2f(tri[1].pos.x(), tri[0].pos.y());
tri[3].tex = tri[0].tex;
tri[4].tex = tri[1].tex;
tri[5].tex = Vector2f(tri[1].tex.x(), tri[0].tex.y());
// advance // advance
x += glyph->advance.x(); x += glyph->advance.x();
@ -677,9 +630,6 @@ TextCache* Font::buildTextCache(const std::string& text, Vector2f offset, unsign
vertList.textureIdPtr = &it->first->textureId; vertList.textureIdPtr = &it->first->textureId;
vertList.verts = it->second; vertList.verts = it->second;
vertList.colors.resize(4 * it->second.size());
Renderer::buildGLColorArray(vertList.colors.data(), color, (unsigned int)(it->second.size()));
} }
clearFaceCache(); clearFaceCache();
@ -694,8 +644,11 @@ TextCache* Font::buildTextCache(const std::string& text, float offsetX, float of
void TextCache::setColor(unsigned int color) void TextCache::setColor(unsigned int color)
{ {
for(auto it = vertexLists.cbegin(); it != vertexLists.cend(); it++) const unsigned int convertedColor = Renderer::convertColor(color);
Renderer::buildGLColorArray((GLubyte*)(it->colors.data()), color, (unsigned int)(it->verts.size()));
for(auto it = vertexLists.begin(); it != vertexLists.end(); it++)
for(auto it2 = it->verts.begin(); it2 != it->verts.end(); it2++)
it2->col = convertedColor;
} }
std::shared_ptr<Font> Font::getFromTheme(const ThemeData::ThemeElement* elem, unsigned int properties, const std::shared_ptr<Font>& orig) std::shared_ptr<Font> Font::getFromTheme(const ThemeData::ThemeElement* elem, unsigned int properties, const std::shared_ptr<Font>& orig)

View file

@ -4,8 +4,8 @@
#include "math/Vector2f.h" #include "math/Vector2f.h"
#include "math/Vector2i.h" #include "math/Vector2i.h"
#include "renderers/Renderer.h"
#include "resources/ResourceManager.h" #include "resources/ResourceManager.h"
#include "Renderer.h"
#include "ThemeData.h" #include "ThemeData.h"
#include <ft2build.h> #include <ft2build.h>
#include FT_FREETYPE_H #include FT_FREETYPE_H
@ -74,7 +74,7 @@ private:
struct FontTexture struct FontTexture
{ {
GLuint textureId; unsigned int textureId;
Vector2i textureSize; Vector2i textureSize;
Vector2i writePos; Vector2i writePos;
@ -141,17 +141,11 @@ private:
class TextCache class TextCache
{ {
protected: protected:
struct Vertex
{
Vector2f pos;
Vector2f tex;
};
struct VertexList struct VertexList
{ {
GLuint* textureIdPtr; // this is a pointer because the texture ID can change during deinit/reinit (when launching a game) std::vector<Renderer::Vertex> verts;
std::vector<Vertex> verts; unsigned int* textureIdPtr; // this is a pointer because the texture ID can change during deinit/reinit (when launching a game)
std::vector<GLubyte> colors;
}; };
std::vector<VertexList> vertexLists; std::vector<VertexList> vertexLists;

View file

@ -1,11 +1,10 @@
#include "resources/TextureData.h" #include "resources/TextureData.h"
#include "math/Misc.h" #include "math/Misc.h"
#include "renderers/Renderer.h"
#include "resources/ResourceManager.h" #include "resources/ResourceManager.h"
#include "ImageIO.h" #include "ImageIO.h"
#include "Log.h" #include "Log.h"
#include "platform.h"
#include GLHEADER
#include <nanosvg/nanosvg.h> #include <nanosvg/nanosvg.h>
#include <nanosvg/nanosvgrast.h> #include <nanosvg/nanosvgrast.h>
#include <assert.h> #include <assert.h>
@ -162,7 +161,7 @@ bool TextureData::uploadAndBind()
std::unique_lock<std::mutex> lock(mMutex); std::unique_lock<std::mutex> lock(mMutex);
if (mTextureID != 0) if (mTextureID != 0)
{ {
glBindTexture(GL_TEXTURE_2D, mTextureID); Renderer::bindTexture(mTextureID);
} }
else else
{ {
@ -174,19 +173,9 @@ bool TextureData::uploadAndBind()
// Make sure we're ready to upload // Make sure we're ready to upload
if ((mWidth == 0) || (mHeight == 0) || (mDataRGBA == nullptr)) if ((mWidth == 0) || (mHeight == 0) || (mDataRGBA == nullptr))
return false; return false;
glGetError();
//now for the openGL texture stuff
glGenTextures(1, &mTextureID);
glBindTexture(GL_TEXTURE_2D, mTextureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)mWidth, (GLsizei)mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, mDataRGBA); // Upload texture
mTextureID = Renderer::createTexture(Renderer::Texture::RGBA, true, mTile, mWidth, mHeight, mDataRGBA);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
const GLint wrapMode = mTile ? GL_REPEAT : GL_CLAMP_TO_EDGE;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
} }
return true; return true;
} }
@ -196,7 +185,7 @@ void TextureData::releaseVRAM()
std::unique_lock<std::mutex> lock(mMutex); std::unique_lock<std::mutex> lock(mMutex);
if (mTextureID != 0) if (mTextureID != 0)
{ {
glDeleteTextures(1, &mTextureID); Renderer::destroyTexture(mTextureID);
mTextureID = 0; mTextureID = 0;
} }
} }

View file

@ -2,8 +2,6 @@
#ifndef ES_CORE_RESOURCES_TEXTURE_DATA_H #ifndef ES_CORE_RESOURCES_TEXTURE_DATA_H
#define ES_CORE_RESOURCES_TEXTURE_DATA_H #define ES_CORE_RESOURCES_TEXTURE_DATA_H
#include "platform.h"
#include GLHEADER
#include <mutex> #include <mutex>
#include <string> #include <string>
@ -53,7 +51,7 @@ private:
std::mutex mMutex; std::mutex mMutex;
bool mTile; bool mTile;
std::string mPath; std::string mPath;
GLuint mTextureID; unsigned int mTextureID;
unsigned char* mDataRGBA; unsigned char* mDataRGBA;
size_t mWidth; size_t mWidth;
size_t mHeight; size_t mHeight;