Moved to SDL2.

Renderer on the Pi doesn't work at the moment.
This commit is contained in:
Aloshi 2013-08-18 12:17:24 -05:00
parent b5fe2cc8fc
commit 09726348b3
8 changed files with 228 additions and 60 deletions

View file

@ -0,0 +1,163 @@
# Locate SDL2 library
# This module defines
# SDL2_LIBRARY, the name of the library to link against
# SDL2_FOUND, if false, do not try to link to SDL2
# SDL2_INCLUDE_DIR, where to find SDL.h
#
# This module responds to the the flag:
# SDL2_BUILDING_LIBRARY
# If this is defined, then no SDL2main will be linked in because
# only applications need main().
# Otherwise, it is assumed you are building an application and this
# module will attempt to locate and set the the proper link flags
# as part of the returned SDL2_LIBRARY variable.
#
# Don't forget to include SDLmain.h and SDLmain.m your project for the
# OS X framework based version. (Other versions link to -lSDL2main which
# this module will try to find on your behalf.) Also for OS X, this
# module will automatically add the -framework Cocoa on your behalf.
#
#
# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration
# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library
# (SDL2.dll, libsdl2.so, SDL2.framework, etc).
# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again.
# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value
# as appropriate. These values are used to generate the final SDL2_LIBRARY
# variable, but when these values are unset, SDL2_LIBRARY does not get created.
#
#
# $SDL2DIR is an environment variable that would
# correspond to the ./configure --prefix=$SDL2DIR
# used in building SDL2.
# l.e.galup 9-20-02
#
# Modified by Eric Wing.
# Added code to assist with automated building by using environmental variables
# and providing a more controlled/consistent search behavior.
# Added new modifications to recognize OS X frameworks and
# additional Unix paths (FreeBSD, etc).
# Also corrected the header search path to follow "proper" SDL guidelines.
# Added a search for SDL2main which is needed by some platforms.
# Added a search for threads which is needed by some platforms.
# Added needed compile switches for MinGW.
#
# On OSX, this will prefer the Framework version (if found) over others.
# People will have to manually change the cache values of
# SDL2_LIBRARY to override this selection or set the CMake environment
# CMAKE_INCLUDE_PATH to modify the search paths.
#
# Note that the header path has changed from SDL2/SDL.h to just SDL.h
# This needed to change because "proper" SDL convention
# is #include "SDL.h", not <SDL2/SDL.h>. This is done for portability
# reasons because not all systems place things in SDL2/ (see FreeBSD).
#=============================================================================
# Copyright 2003-2009 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
SET(SDL2_SEARCH_PATHS
~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
/opt
)
FIND_PATH(SDL2_INCLUDE_DIR SDL.h
HINTS
$ENV{SDL2DIR}
PATH_SUFFIXES include/SDL2 include
PATHS ${SDL2_SEARCH_PATHS}
)
FIND_LIBRARY(SDL2_LIBRARY_TEMP
NAMES SDL2
HINTS
$ENV{SDL2DIR}
PATH_SUFFIXES lib64 lib
PATHS ${SDL2_SEARCH_PATHS}
)
IF(NOT SDL2_BUILDING_LIBRARY)
IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
# Non-OS X framework versions expect you to also dynamically link to
# SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms
# seem to provide SDL2main for compatibility even though they don't
# necessarily need it.
FIND_LIBRARY(SDL2MAIN_LIBRARY
NAMES SDL2main
HINTS
$ENV{SDL2DIR}
PATH_SUFFIXES lib64 lib
PATHS ${SDL2_SEARCH_PATHS}
)
ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
ENDIF(NOT SDL2_BUILDING_LIBRARY)
# SDL2 may require threads on your system.
# The Apple build may not need an explicit flag because one of the
# frameworks may already provide it.
# But for non-OSX systems, I will use the CMake Threads package.
IF(NOT APPLE)
FIND_PACKAGE(Threads)
ENDIF(NOT APPLE)
# MinGW needs an additional library, mwindows
# It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -lmwindows
# (Actually on second look, I think it only needs one of the m* libraries.)
IF(MINGW)
SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW")
ENDIF(MINGW)
IF(SDL2_LIBRARY_TEMP)
# For SDL2main
IF(NOT SDL2_BUILDING_LIBRARY)
IF(SDL2MAIN_LIBRARY)
SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP})
ENDIF(SDL2MAIN_LIBRARY)
ENDIF(NOT SDL2_BUILDING_LIBRARY)
# For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa.
# CMake doesn't display the -framework Cocoa string in the UI even
# though it actually is there if I modify a pre-used variable.
# I think it has something to do with the CACHE STRING.
# So I use a temporary variable until the end so I can set the
# "real" variable in one-shot.
IF(APPLE)
SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa")
ENDIF(APPLE)
# For threads, as mentioned Apple doesn't need this.
# In fact, there seems to be a problem if I used the Threads package
# and try using this line, so I'm just skipping it entirely for OS X.
IF(NOT APPLE)
SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT})
ENDIF(NOT APPLE)
# For MinGW library
IF(MINGW)
SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP})
ENDIF(MINGW)
# Set the final string here so the GUI reflects the final state.
SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found")
# Set the temp variable to INTERNAL so it is not seen in the CMake GUI
SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "")
ENDIF(SDL2_LIBRARY_TEMP)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR)

View file

@ -34,7 +34,7 @@ else()
endif() endif()
find_package(FreeType REQUIRED) find_package(FreeType REQUIRED)
find_package(FreeImage REQUIRED) find_package(FreeImage REQUIRED)
find_package(SDL REQUIRED) find_package(SDL2 REQUIRED)
find_package(Boost REQUIRED COMPONENTS system filesystem) find_package(Boost REQUIRED COMPONENTS system filesystem)
find_package(Eigen3 REQUIRED) find_package(Eigen3 REQUIRED)
@ -81,7 +81,7 @@ add_definitions(-DEIGEN_DONT_ALIGN)
set(ES_INCLUDE_DIRS set(ES_INCLUDE_DIRS
${FREETYPE_INCLUDE_DIRS} ${FREETYPE_INCLUDE_DIRS}
${FreeImage_INCLUDE_DIRS} ${FreeImage_INCLUDE_DIRS}
${SDL_INCLUDE_DIR} ${SDL2_INCLUDE_DIR}
${Boost_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}
${EIGEN3_INCLUDE_DIR} ${EIGEN3_INCLUDE_DIR}
) )
@ -252,8 +252,8 @@ set(ES_LIBRARIES
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${FREETYPE_LIBRARIES} ${FREETYPE_LIBRARIES}
${FreeImage_LIBRARIES} ${FreeImage_LIBRARIES}
${SDL_LIBRARY} ${SDL2_LIBRARY}
${SDLMAIN_LIBRARY} ${SDL2MAIN_LIBRARY}
) )
#add ALSA for Linux #add ALSA for Linux

View file

@ -14,6 +14,9 @@ void AudioManager::mixAudio(void *unused, Uint8 *stream, int len)
{ {
bool stillPlaying = false; bool stillPlaying = false;
//initialize the buffer to "silence"
SDL_memset(stream, 0, len);
//iterate through all our samples //iterate through all our samples
std::vector<std::shared_ptr<Sound>>::const_iterator soundIt = sSoundVector.cbegin(); std::vector<std::shared_ptr<Sound>>::const_iterator soundIt = sSoundVector.cbegin();
while (soundIt != sSoundVector.cend()) while (soundIt != sSoundVector.cend())
@ -40,6 +43,7 @@ void AudioManager::mixAudio(void *unused, Uint8 *stream, int len)
//advance to next sound //advance to next sound
++soundIt; ++soundIt;
} }
//we have processed all samples. check if some will still be playing //we have processed all samples. check if some will still be playing
if (!stillPlaying) { if (!stillPlaying) {
//no. pause audio till a Sound::play() wakes us up //no. pause audio till a Sound::play() wakes us up

View file

@ -4,6 +4,7 @@
#include <SDL.h> #include <SDL.h>
#include <iostream> #include <iostream>
#include "Log.h" #include "Log.h"
#include "InputManager.h"
//some util functions //some util functions
std::string inputTypeToString(InputType type) std::string inputTypeToString(InputType type)
@ -48,7 +49,7 @@ std::string toLower(std::string str)
} }
//end util functions //end util functions
InputConfig::InputConfig(int deviceId) : mDeviceId(deviceId) InputConfig::InputConfig(int deviceId, const std::string& deviceName) : mDeviceId(deviceId), mDeviceName(deviceName)
{ {
mPlayerNum = -1; mPlayerNum = -1;
} }
@ -162,7 +163,7 @@ void InputConfig::writeToXML(pugi::xml_node parent)
cfg.append_attribute("type") = "keyboard"; cfg.append_attribute("type") = "keyboard";
}else{ }else{
cfg.append_attribute("type") = "joystick"; cfg.append_attribute("type") = "joystick";
cfg.append_attribute("deviceName") = SDL_JoystickName(mDeviceId); cfg.append_attribute("deviceName") = mDeviceName.c_str();
} }
typedef std::map<std::string, Input>::iterator it_type; typedef std::map<std::string, Input>::iterator it_type;

View file

@ -72,7 +72,7 @@ public:
stream << "Hat " << id << " " << getHatDir(value); stream << "Hat " << id << " " << getHatDir(value);
break; break;
case TYPE_KEY: case TYPE_KEY:
stream << "Key " << SDL_GetKeyName((SDLKey)id); stream << "Key " << SDL_GetKeyName((SDL_Keycode)id);
break; break;
default: default:
stream << "Input to string error"; stream << "Input to string error";
@ -86,7 +86,7 @@ public:
class InputConfig class InputConfig
{ {
public: public:
InputConfig(int deviceId); InputConfig(int deviceId, const std::string& deviceName);
void clear(); void clear();
void mapInput(const std::string& name, Input input); void mapInput(const std::string& name, Input input);
@ -109,6 +109,7 @@ public:
private: private:
std::map<std::string, Input> mNameMap; std::map<std::string, Input> mNameMap;
const int mDeviceId; const int mDeviceId;
const std::string mDeviceName;
int mPlayerNum; int mPlayerNum;
}; };

View file

@ -126,7 +126,7 @@ Uint32 InputManager::devicePollingCallback(Uint32 interval, void* param)
event.user.code = SDL_USEREVENT_POLLDEVICES; event.user.code = SDL_USEREVENT_POLLDEVICES;
event.user.data1 = nullptr; event.user.data1 = nullptr;
event.user.data2 = nullptr; event.user.data2 = nullptr;
if (SDL_PushEvent(&event) != 0) { if (!SDL_PushEvent(&event)) {
LOG(LogError) << "InputManager::devicePollingCallback - SDL event queue is full!"; LOG(LogError) << "InputManager::devicePollingCallback - SDL event queue is full!";
} }
@ -151,7 +151,7 @@ void InputManager::init()
for(int i = 0; i < mNumJoysticks; i++) for(int i = 0; i < mNumJoysticks; i++)
{ {
mJoysticks[i] = SDL_JoystickOpen(i); mJoysticks[i] = SDL_JoystickOpen(i);
mInputConfigs[i] = new InputConfig(i); mInputConfigs[i] = new InputConfig(i, SDL_JoystickName(mJoysticks[i]));
for(int k = 0; k < SDL_JoystickNumAxes(mJoysticks[i]); k++) for(int k = 0; k < SDL_JoystickNumAxes(mJoysticks[i]); k++)
{ {
@ -159,7 +159,7 @@ void InputManager::init()
} }
} }
mKeyboardInputConfig = new InputConfig(DEVICE_KEYBOARD); mKeyboardInputConfig = new InputConfig(DEVICE_KEYBOARD, "Keyboard");
SDL_JoystickEventState(SDL_ENABLE); SDL_JoystickEventState(SDL_ENABLE);
@ -370,7 +370,7 @@ void InputManager::loadConfig()
std::string devName = node.attribute("deviceName").as_string(); std::string devName = node.attribute("deviceName").as_string();
for(int i = 0; i < mNumJoysticks; i++) for(int i = 0; i < mNumJoysticks; i++)
{ {
if(!configuredDevice[i] && SDL_JoystickName(i) == devName) if(!configuredDevice[i] && SDL_JoystickName(mJoysticks[i]) == devName)
{ {
mInputConfigs[i]->loadFromXML(node, mNumPlayers); mInputConfigs[i]->loadFromXML(node, mNumPlayers);
mNumPlayers++; mNumPlayers++;

View file

@ -12,7 +12,8 @@ class GuiComponent;
class Font; class Font;
//The Renderer provides several higher-level functions for drawing (rectangles, text, etc.). //The Renderer provides several higher-level functions for drawing (rectangles, text, etc.).
//Defined in multiple files - Renderer.cpp has the GuiComponent stuff, Renderer_draw_* includes renderer-specific drawing implementations, and Renderer_init_* includes renderer-specific init/deinit. //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 namespace Renderer
{ {
bool init(int w, int h); bool init(int w, int h);

View file

@ -1,16 +1,9 @@
#include "Renderer.h" #include "Renderer.h"
#include <iostream> #include <iostream>
#include "platform.h" #include "platform.h"
#ifdef _WINDOWS_
#include <Windows.h>
#endif
#include GLHEADER #include GLHEADER
#include "Font.h" #include "Font.h"
#include <SDL.h> #include <SDL.h>
#include "InputManager.h"
#include "Log.h" #include "Log.h"
#include "ImageIO.h" #include "ImageIO.h"
#include "../data/Resources.h" #include "../data/Resources.h"
@ -27,9 +20,10 @@ namespace Renderer
unsigned int getScreenWidth() { return display_width; } unsigned int getScreenWidth() { return display_width; }
unsigned int getScreenHeight() { return display_height; } unsigned int getScreenHeight() { return display_height; }
SDL_Surface* sdlScreen = NULL; SDL_Window* sdlWindow = NULL;
SDL_GLContext sdlContext = NULL;
bool createSurface() //unsigned int display_width, unsigned int display_height) bool createSurface()
{ {
LOG(LogInfo) << "Creating surface..."; LOG(LogInfo) << "Creating surface...";
@ -39,53 +33,54 @@ namespace Renderer
return false; return false;
} }
//ATM it is best to just leave the window icon alone on windows.
//When compiled as a Windows application, ES at least has an icon in the taskbar
//The method below looks pretty shite as alpha isn't taken into account...
#ifndef WIN32
//try loading PNG from memory
size_t width = 0;
size_t height = 0;
std::vector<unsigned char> rawData = ImageIO::loadFromMemoryRGBA32(ES_logo_32_png_data, ES_logo_32_png_size, width, height);
if (!rawData.empty()) {
//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 = 0x0000ff00; Uint32 bmask = 0x00ff0000; Uint32 amask = 0x000000ff;
#else
Uint32 rmask = 0x000000ff; Uint32 gmask = 0x00ff0000; Uint32 bmask = 0x0000ff00; Uint32 amask = 0xff000000;
#endif
//try creating SDL surface from logo data
SDL_Surface * logoSurface = SDL_CreateRGBSurfaceFrom((void *)rawData.data(), width, height, 32, width*4, rmask, gmask, bmask, amask);
if (logoSurface != nullptr) {
//change window icon. this sucks atm, but there's nothing better we can do. SDL 1.3 or 2.0 should sort this out...
SDL_WM_SetIcon(logoSurface, nullptr);
}
}
#endif
SDL_WM_SetCaption("EmulationStation", "EmulationStation");
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
//SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); //vsync //SDL_GL_SetSwapInterval(1); //0 for immediate updates, 1 for updates synchronized with the vertical retrace, -1 for late swap tearing
sdlScreen = SDL_SetVideoMode(display_width, display_height, 16, SDL_OPENGL | (Settings::getInstance()->getBool("WINDOWED") ? 0 : SDL_FULLSCREEN));
if(sdlScreen == NULL) sdlWindow = SDL_CreateWindow("EmulationStation",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
display_width, display_height,
SDL_WINDOW_OPENGL | (Settings::getInstance()->getBool("WINDOWED") ? 0 : SDL_WINDOW_FULLSCREEN));
if(sdlWindow == NULL)
{ {
LOG(LogError) << "Error creating SDL video surface!"; LOG(LogError) << "Error creating SDL window!";
return false; return false;
} }
LOG(LogInfo) << "Created window successfully.";
//set an icon for the window
size_t width = 0;
size_t height = 0;
std::vector<unsigned char> rawData = ImageIO::loadFromMemoryRGBA32(ES_logo_32_png_data, ES_logo_32_png_size, width, height);
if (!rawData.empty())
{
//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(), width, height, 32, width * 4, rmask, gmask, bmask, amask);
if (logoSurface != NULL)
{
SDL_SetWindowIcon(sdlWindow, logoSurface);
SDL_FreeSurface(logoSurface);
}
}
sdlContext = SDL_GL_CreateContext(sdlWindow);
//usually display width/height are not specified, i.e. zero, which SDL automatically takes as "native resolution" //usually display width/height are not specified, i.e. zero, which SDL automatically takes as "native resolution"
//so, since other things rely on the size of the screen (damn currently unnormalized coordinate system), we set it here //so, since other things rely on the size of the screen (damn currently unnormalized coordinate system), we set it here
//even though the system was already initialized //even though the system was already initialized - this makes sure it gets reinitialized to the original resolution when we return from a game
display_width = sdlScreen->w; //display_width = sdlWindow->w;
display_height = sdlScreen->h; //display_height = sdlWindow->h;
LOG(LogInfo) << "Created surface successfully.";
//hide mouse cursor //hide mouse cursor
initialCursorState = SDL_ShowCursor(0) == 1; initialCursorState = SDL_ShowCursor(0) == 1;
@ -95,14 +90,17 @@ namespace Renderer
void swapBuffers() void swapBuffers()
{ {
SDL_GL_SwapBuffers(); SDL_GL_SwapWindow(sdlWindow);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
} }
void destroySurface() void destroySurface()
{ {
SDL_FreeSurface(sdlScreen); SDL_GL_DeleteContext(sdlContext);
sdlScreen = NULL; sdlContext = NULL;
SDL_DestroyWindow(sdlWindow);
sdlWindow = NULL;
//show mouse cursor //show mouse cursor
SDL_ShowCursor(initialCursorState); SDL_ShowCursor(initialCursorState);