SDL: Add experimental support for SDL2.

This is based upon skristiansson's change set to make ScummVM work with SDL2.
This commit is contained in:
Johannes Schickel 2015-01-25 01:34:57 +01:00
parent defe71792d
commit 8530997fff
13 changed files with 606 additions and 49 deletions

View file

@ -63,8 +63,14 @@ SdlEventSource::SdlEventSource()
// Enable joystick
if (SDL_NumJoysticks() > joystick_num) {
debug("Using joystick: %s", SDL_JoystickName(joystick_num));
_joystick = SDL_JoystickOpen(joystick_num);
debug("Using joystick: %s",
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_JoystickName(_joystick)
#else
SDL_JoystickName(joystick_num)
#endif
);
} else {
warning("Invalid joystick: %d", joystick_num);
}
@ -76,21 +82,24 @@ SdlEventSource::~SdlEventSource() {
SDL_JoystickClose(_joystick);
}
int SdlEventSource::mapKey(SDLKey key, SDLMod mod, Uint16 unicode) {
if (key >= SDLK_F1 && key <= SDLK_F9) {
int SdlEventSource::mapKey(SDLKey sdlKey, SDLMod mod, Uint16 unicode) {
Common::KeyCode key = SDLToOSystemKeycode(sdlKey);
if (key >= Common::KEYCODE_F1 && key <= Common::KEYCODE_F9) {
return key - SDLK_F1 + Common::ASCII_F1;
} else if (key >= SDLK_KP0 && key <= SDLK_KP9) {
return key - SDLK_KP0 + '0';
} else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) {
} else if (key >= Common::KEYCODE_KP0 && key <= Common::KEYCODE_KP9) {
return key - Common::KEYCODE_KP0 + '0';
} else if (key >= Common::KEYCODE_UP && key <= Common::KEYCODE_PAGEDOWN) {
return key;
} else if (unicode) {
return unicode;
} else if (key >= 'a' && key <= 'z' && (mod & KMOD_SHIFT)) {
return key & ~0x20;
} else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) {
} else if (key >= Common::KEYCODE_NUMLOCK && key <= Common::KEYCODE_EURO) {
return 0;
} else {
return key;
}
return key;
}
void SdlEventSource::processMouseEvent(Common::Event &event, int x, int y) {
@ -342,7 +351,9 @@ Common::KeyCode SdlEventSource::SDLToOSystemKeycode(const SDLKey key) {
case SDLK_HELP: return Common::KEYCODE_HELP;
case SDLK_PRINT: return Common::KEYCODE_PRINT;
case SDLK_SYSREQ: return Common::KEYCODE_SYSREQ;
#if !SDL_VERSION_ATLEAST(2, 0, 0)
case SDLK_BREAK: return Common::KEYCODE_BREAK;
#endif
case SDLK_MENU: return Common::KEYCODE_MENU;
case SDLK_POWER: return Common::KEYCODE_POWER;
case SDLK_UNDO: return Common::KEYCODE_UNDO;
@ -389,24 +400,52 @@ bool SdlEventSource::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) {
case SDL_JOYAXISMOTION:
return handleJoyAxisMotion(ev, event);
#if SDL_VERSION_ATLEAST(2, 0, 0)
case SDL_MOUSEWHEEL: {
Sint32 yDir = ev.wheel.y;
#if SDL_VERSION_ATLEAST(2, 0, 4)
if (ev.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) {
yDir *= -1;
}
#endif
// HACK: It seems we want the mouse coordinates supplied
// with a mouse wheel event. However, SDL2 does not supply
// these, thus we use whatever we got last time. It seems
// these are always stored in _km.x, _km.y.
processMouseEvent(event, _km.x, _km.y);
if (yDir < 0) {
event.type = Common::EVENT_WHEELDOWN;
return true;
} else if (yDir > 0) {
event.type = Common::EVENT_WHEELUP;
return true;
} else {
return false;
}
}
case SDL_WINDOWEVENT:
switch (ev.window.event) {
case SDL_WINDOWEVENT_EXPOSED:
if (_graphicsManager)
_graphicsManager->notifyVideoExpose();
return false;
case SDL_WINDOWEVENT_RESIZED:
return handleResizeEvent(event, ev.window.data1, ev.window.data2);
default:
return false;
}
#else
case SDL_VIDEOEXPOSE:
if (_graphicsManager)
_graphicsManager->notifyVideoExpose();
return false;
case SDL_VIDEORESIZE:
if (_graphicsManager) {
_graphicsManager->notifyResize(ev.resize.w, ev.resize.h);
// If the screen changed, send an Common::EVENT_SCREEN_CHANGED
int screenID = ((OSystem_SDL *)g_system)->getGraphicsManager()->getScreenChangeID();
if (screenID != _lastScreenID) {
_lastScreenID = screenID;
event.type = Common::EVENT_SCREEN_CHANGED;
return true;
}
}
return false;
return handleResizeEvent(event, ev.resize.w, ev.resize.h);
#endif
case SDL_QUIT:
event.type = Common::EVENT_QUIT;
@ -476,7 +515,7 @@ bool SdlEventSource::handleKeyDown(SDL_Event &ev, Common::Event &event) {
event.type = Common::EVENT_KEYDOWN;
event.kbd.keycode = SDLToOSystemKeycode(ev.key.keysym.sym);
event.kbd.ascii = mapKey(ev.key.keysym.sym, (SDLMod)ev.key.keysym.mod, (Uint16)ev.key.keysym.unicode);
event.kbd.ascii = mapKey(ev.key.keysym.sym, (SDLMod)ev.key.keysym.mod, obtainUnicode(ev.key.keysym));
return true;
}
@ -520,7 +559,7 @@ bool SdlEventSource::handleKeyUp(SDL_Event &ev, Common::Event &event) {
event.type = Common::EVENT_KEYUP;
event.kbd.keycode = SDLToOSystemKeycode(ev.key.keysym.sym);
event.kbd.ascii = mapKey(ev.key.keysym.sym, (SDLMod)ev.key.keysym.mod, (Uint16)ev.key.keysym.unicode);
event.kbd.ascii = mapKey(ev.key.keysym.sym, (SDLMod)ev.key.keysym.mod, 0);
// Ctrl-Alt-<key> will change the GFX mode
SDLModToOSystemKeyFlags(mod, event);
@ -763,4 +802,64 @@ void SdlEventSource::resetKeyboadEmulation(int16 x_max, int16 y_max) {
_km.last_time = 0;
}
bool SdlEventSource::handleResizeEvent(Common::Event &event, int w, int h) {
if (_graphicsManager) {
_graphicsManager->notifyResize(w, h);
// If the screen changed, send an Common::EVENT_SCREEN_CHANGED
int screenID = ((OSystem_SDL *)g_system)->getGraphicsManager()->getScreenChangeID();
if (screenID != _lastScreenID) {
_lastScreenID = screenID;
event.type = Common::EVENT_SCREEN_CHANGED;
return true;
}
}
return false;
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
static uint32 convUTF8ToUTF32(const char *src) {
uint32 utf32 = 0;
char *dst = SDL_iconv_string(
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
"UTF-32BE",
#else
"UTF-32LE",
#endif
"UTF-8", src, SDL_strlen(src) + 1);
if (dst) {
utf32 = *((uint32 *)dst);
SDL_free(dst);
}
return utf32;
}
#endif
uint32 SdlEventSource::obtainUnicode(const SDL_keysym keySym) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_Event events[2];
// In SDL2, the unicode field has been removed from the keysym struct.
// Instead a SDL_TEXTINPUT event is generated on key combinations that
// generates unicode.
// Here we peek into the event queue for the event to see if it exists.
int n = SDL_PeepEvents(events, 2, SDL_PEEKEVENT, SDL_KEYDOWN, SDL_TEXTINPUT);
// Make sure that the TEXTINPUT event belongs to this KEYDOWN
// event and not another pending one.
if (n > 0 && events[0].type == SDL_TEXTINPUT) {
return convUTF8ToUTF32(events[0].text.text);
} else if (n > 1 && events[0].type != SDL_KEYDOWN && events[1].type == SDL_TEXTINPUT) {
return convUTF8ToUTF32(events[1].text.text);
} else {
return 0;
}
#else
return keySym.unicode;
#endif
}
#endif

View file

@ -125,7 +125,7 @@ protected:
/**
* Maps the ASCII value of key
*/
virtual int mapKey(SDLKey key, SDLMod mod, Uint16 unicode);
int mapKey(SDLKey key, SDLMod mod, Uint16 unicode);
/**
* Configures the key modifiers flags status
@ -136,6 +136,17 @@ protected:
* Translates SDL key codes to OSystem key codes
*/
Common::KeyCode SDLToOSystemKeycode(const SDLKey key);
/**
* Notify graphics manager of a resize request.
*/
bool handleResizeEvent(Common::Event &event, int w, int h);
/**
* Extracts unicode information for the specific key sym.
* May only be used for key down events.
*/
uint32 obtainUnicode(const SDL_keysym keySym);
};
#endif

View file

@ -29,7 +29,12 @@
#endif
OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint desktopHeight, SdlEventSource *eventSource)
: SdlGraphicsManager(eventSource), _lastVideoModeLoad(0), _hwScreen(nullptr), _lastRequestedWidth(0), _lastRequestedHeight(0),
: SdlGraphicsManager(eventSource), _lastRequestedHeight(0),
#if SDL_VERSION_ATLEAST(2, 0, 0)
_glContext(),
#else
_lastVideoModeLoad(0), _hwScreen(nullptr),
#endif
_graphicsScale(2), _ignoreLoadVideoMode(false), _gotResize(false), _wantsFullScreen(false), _ignoreResizeEvents(0),
_desiredFullscreenWidth(0), _desiredFullscreenHeight(0) {
// Setup OpenGL attributes for SDL
@ -40,6 +45,17 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
// Retrieve a list of working fullscreen modes
#if SDL_VERSION_ATLEAST(2, 0, 0)
const int numModes = SDL_GetNumDisplayModes(0);
for (int i = 0; i < numModes; ++i) {
SDL_DisplayMode mode;
if (SDL_GetDisplayMode(0, i, &mode)) {
continue;
}
_fullscreenVideoModes.push_back(VideoMode(mode.w, mode.h));
}
#else
const SDL_Rect *const *availableModes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN);
if (availableModes != (void *)-1) {
for (;*availableModes; ++availableModes) {
@ -47,9 +63,19 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt
_fullscreenVideoModes.push_back(VideoMode(mode->w, mode->h));
}
}
#endif
// Sort the modes in ascending order.
Common::sort(_fullscreenVideoModes.begin(), _fullscreenVideoModes.end());
// Sort the modes in ascending order.
Common::sort(_fullscreenVideoModes.begin(), _fullscreenVideoModes.end());
// Strip duplicates in video modes.
for (uint i = 0; i + 1 < _fullscreenVideoModes.size();) {
if (_fullscreenVideoModes[i] == _fullscreenVideoModes[i + 1]) {
_fullscreenVideoModes.remove_at(i);
} else {
++i;
}
}
// In case SDL is fine with every mode we will force the desktop mode.
@ -120,11 +146,19 @@ void OpenGLSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable)
bool OpenGLSdlGraphicsManager::getFeatureState(OSystem::Feature f) {
switch (f) {
case OSystem::kFeatureFullscreenMode:
#if SDL_VERSION_ATLEAST(2, 0, 0)
if (_window) {
return (SDL_GetWindowFlags(_window) & SDL_WINDOW_FULLSCREEN) != 0;
} else {
return _wantsFullScreen;
}
#else
if (_hwScreen) {
return (_hwScreen->flags & SDL_FULLSCREEN) != 0;
} else {
return _wantsFullScreen;
}
#endif
default:
return OpenGLGraphicsManager::getFeatureState(f);
@ -201,13 +235,20 @@ void OpenGLSdlGraphicsManager::updateScreen() {
OpenGLGraphicsManager::updateScreen();
// Swap OpenGL buffers
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_GL_SwapWindow(_window);
#else
SDL_GL_SwapBuffers();
#endif
}
void OpenGLSdlGraphicsManager::notifyVideoExpose() {
}
void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
setActualScreenSize(width, height);
#else
if (!_ignoreResizeEvents && _hwScreen && !(_hwScreen->flags & SDL_FULLSCREEN)) {
// We save that we handled a resize event here. We need to know this
// so we do not overwrite the users requested window size whenever we
@ -218,6 +259,7 @@ void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height)
g_system->quit();
}
}
#endif
}
void OpenGLSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) {
@ -300,6 +342,58 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
height = _desiredFullscreenHeight;
}
// This is pretty confusing since RGBA8888 talks about the memory
// layout here. This is a different logical layout depending on
// whether we run on little endian or big endian. However, we can
// only safely assume that RGBA8888 in memory layout is supported.
// Thus, we chose this one.
const Graphics::PixelFormat rgba8888 =
#ifdef SCUMM_LITTLE_ENDIAN
Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24);
#else
Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
#endif
#if SDL_VERSION_ATLEAST(2, 0, 0)
if (_glContext) {
notifyContextDestroy();
SDL_GL_DeleteContext(_glContext);
_glContext = nullptr;
}
destroyWindow();
uint32 flags = SDL_WINDOW_OPENGL;
if (_wantsFullScreen) {
flags |= SDL_WINDOW_FULLSCREEN;
} else {
flags |= SDL_WINDOW_RESIZABLE;
}
if (!createWindow(width, height, flags)) {
// We treat fullscreen requests as a "hint" for now. This means in
// case it is not available we simply ignore it.
if (_wantsFullScreen) {
createWindow(width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
}
if (!_window) {
return false;
}
}
_glContext = SDL_GL_CreateContext(_window);
if (!_glContext) {
return false;
}
notifyContextCreate(rgba8888, rgba8888);
int actualWidth, actualHeight;
SDL_GetWindowSize(_window, &actualWidth, &actualHeight);
setActualScreenSize(actualWidth, actualHeight);
return true;
#else
// WORKAROUND: Working around infamous SDL bugs when switching
// resolutions too fast. This might cause the event system to supply
// incorrect mouse position events otherwise.
@ -341,17 +435,6 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
_lastVideoModeLoad = SDL_GetTicks();
if (_hwScreen) {
// This is pretty confusing since RGBA8888 talks about the memory
// layout here. This is a different logical layout depending on
// whether we run on little endian or big endian. However, we can
// only safely assume that RGBA8888 in memory layout is supported.
// Thus, we chose this one.
const Graphics::PixelFormat rgba8888 =
#ifdef SCUMM_LITTLE_ENDIAN
Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24);
#else
Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
#endif
notifyContextCreate(rgba8888, rgba8888);
setActualScreenSize(_hwScreen->w, _hwScreen->h);
}
@ -363,6 +446,21 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
_ignoreResizeEvents = 10;
return _hwScreen != nullptr;
#endif
}
void OpenGLSdlGraphicsManager::getWindowDimensions(int *width, int *height) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_GetWindowSize(_window, width, height);
#else
if (width) {
*width = _hwScreen->w;
}
if (height) {
*height = _hwScreen->h;
}
#endif
}
bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
@ -456,7 +554,9 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
// Calculate the next scaling setting. We approximate the
// current scale setting in case the user resized the
// window. Then we apply the direction change.
_graphicsScale = MAX<int>(_hwScreen->w / _lastRequestedWidth, _hwScreen->h / _lastRequestedHeight);
int windowWidth = 0, windowHeight = 0;
getWindowDimensions(&windowWidth, &windowHeight);
_graphicsScale = MAX<int>(windowWidth / _lastRequestedWidth, windowHeight / _lastRequestedHeight);
_graphicsScale = MAX<int>(_graphicsScale + direction, 1);
// Since we overwrite a user resize here we reset its
@ -472,7 +572,9 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
}
#ifdef USE_OSD
const Common::String osdMsg = Common::String::format("Resolution: %dx%d", _hwScreen->w, _hwScreen->h);
int windowWidth = 0, windowHeight = 0;
getWindowDimensions(&windowWidth, &windowHeight);
const Common::String osdMsg = Common::String::format("Resolution: %dx%d", windowWidth, windowHeight);
displayMessageOnOSD(osdMsg.c_str());
#endif

View file

@ -68,8 +68,14 @@ protected:
private:
bool setupMode(uint width, uint height);
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_GLContext _glContext;
#else
uint32 _lastVideoModeLoad;
SDL_Surface *_hwScreen;
#endif
void getWindowDimensions(int *width, int *height);
uint _lastRequestedWidth;
uint _lastRequestedHeight;

View file

@ -27,10 +27,18 @@
#include "common/textconsole.h"
SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *source)
: _eventSource(source) {
: _eventSource(source)
#if SDL_VERSION_ATLEAST(2, 0, 0)
, _window(nullptr), _inputGrabState(false), _windowCaption("ScummVM"), _windowIcon(nullptr)
#endif
{
}
SdlGraphicsManager::~SdlGraphicsManager() {
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_FreeSurface(_windowIcon);
destroyWindow();
#endif
}
void SdlGraphicsManager::activateManager() {
@ -42,34 +50,112 @@ void SdlGraphicsManager::deactivateManager() {
}
void SdlGraphicsManager::setWindowCaption(const Common::String &caption) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
_windowCaption = caption;
if (_window) {
SDL_SetWindowTitle(_window, caption.c_str());
}
#else
SDL_WM_SetCaption(caption.c_str(), caption.c_str());
#endif
}
void SdlGraphicsManager::setWindowIcon(SDL_Surface *icon) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_FreeSurface(_windowIcon);
_windowIcon = icon;
if (_window) {
SDL_SetWindowIcon(_window, icon);
}
#else
SDL_WM_SetIcon(icon, NULL);
SDL_FreeSurface(icon);
#endif
}
void SdlGraphicsManager::toggleMouseGrab() {
#if SDL_VERSION_ATLEAST(2, 0, 0)
if (_window) {
_inputGrabState = !(SDL_GetWindowGrab(_window) == SDL_TRUE);
SDL_SetWindowGrab(_window, _inputGrabState ? SDL_TRUE : SDL_FALSE);
}
#else
if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) {
SDL_WM_GrabInput(SDL_GRAB_ON);
} else {
SDL_WM_GrabInput(SDL_GRAB_OFF);
}
#endif
}
bool SdlGraphicsManager::hasMouseFocus() const {
#if SDL_VERSION_ATLEAST(2, 0, 0)
if (_window) {
return (SDL_GetWindowFlags(_window) & SDL_WINDOW_MOUSE_FOCUS);
} else {
return false;
}
#else
return (SDL_GetAppState() & SDL_APPMOUSEFOCUS);
#endif
}
void SdlGraphicsManager::warpMouseInWindow(uint x, uint y) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
if (_window) {
SDL_WarpMouseInWindow(_window, x, y);
}
#else
SDL_WarpMouse(x, y);
#endif
}
void SdlGraphicsManager::iconifyWindow() {
#if SDL_VERSION_ATLEAST(2, 0, 0)
if (_window) {
SDL_MinimizeWindow(_window);
}
#else
SDL_WM_IconifyWindow();
#endif
}
SdlGraphicsManager::State::State()
#if SDL_VERSION_ATLEAST(2, 0, 0)
: windowIcon(nullptr)
#endif
{
}
SdlGraphicsManager::State::~State() {
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_FreeSurface(windowIcon);
#endif
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_Surface *copySDLSurface(SDL_Surface *src) {
const bool locked = SDL_MUSTLOCK(src) == SDL_TRUE;
if (locked) {
if (SDL_LockSurface(src) != 0) {
return nullptr;
}
}
SDL_Surface *res = SDL_CreateRGBSurfaceFrom(src->pixels,
src->w, src->h, src->format->BitsPerPixel,
src->pitch, src->format->Rmask, src->format->Gmask,
src->format->Bmask, src->format->Amask);
if (locked) {
SDL_UnlockSurface(src);
}
return res;
}
#endif
SdlGraphicsManager::State SdlGraphicsManager::getState() {
State state;
@ -82,10 +168,29 @@ SdlGraphicsManager::State SdlGraphicsManager::getState() {
state.pixelFormat = getScreenFormat();
#endif
#if SDL_VERSION_ATLEAST(2, 0, 0)
state.inputGrabState = _inputGrabState;
state.windowCaption = _windowCaption;
state.windowIcon = copySDLSurface(_windowIcon);
#endif
return state;
}
bool SdlGraphicsManager::setState(const State &state) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
_inputGrabState = state.inputGrabState;
if (!_window) {
_windowCaption = state.windowCaption;
SDL_FreeSurface(_windowIcon);
_windowIcon = copySDLSurface(state.windowIcon);
} else {
SDL_SetWindowGrab(_window, _inputGrabState ? SDL_TRUE : SDL_FALSE);
setWindowCaption(state.windowCaption);
setWindowIcon(copySDLSurface(state.windowIcon));
}
#endif
beginGFXTransaction();
#ifdef USE_RGB_COLOR
initSize(state.screenWidth, state.screenHeight, &state.pixelFormat);
@ -102,3 +207,27 @@ bool SdlGraphicsManager::setState(const State &state) {
return true;
}
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
bool SdlGraphicsManager::createWindow(int width, int height, uint32 flags) {
destroyWindow();
if (_inputGrabState) {
flags |= SDL_WINDOW_INPUT_GRABBED;
}
_window = SDL_CreateWindow(_windowCaption.c_str(), SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, width, height, flags);
if (!_window) {
return false;
}
SDL_SetWindowIcon(_window, _windowIcon);
return true;
}
void SdlGraphicsManager::destroyWindow() {
SDL_DestroyWindow(_window);
_window = nullptr;
}
#endif

View file

@ -134,6 +134,9 @@ public:
* between different SDL graphic managers on runtime.
*/
struct State {
State();
~State();
int screenWidth, screenHeight;
bool aspectRatio;
bool fullscreen;
@ -142,6 +145,12 @@ public:
#ifdef USE_RGB_COLOR
Graphics::PixelFormat pixelFormat;
#endif
#if SDL_VERSION_ATLEAST(2, 0, 0)
bool inputGrabState;
Common::String windowCaption;
SDL_Surface *windowIcon;
#endif
};
/**
@ -156,6 +165,17 @@ public:
protected:
SdlEventSource *_eventSource;
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_Window *_window;
bool createWindow(int width, int height, uint32 flags);
void destroyWindow();
private:
bool _inputGrabState;
Common::String _windowCaption;
SDL_Surface *_windowIcon;
#endif
};
#endif

View file

@ -122,7 +122,11 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
#ifdef USE_OSD
_osdSurface(0), _osdAlpha(SDL_ALPHA_TRANSPARENT), _osdFadeStartTime(0),
#endif
_hwscreen(0), _screen(0), _tmpscreen(0),
_hwscreen(0),
#if SDL_VERSION_ATLEAST(2, 0, 0)
_renderer(nullptr), _screenTexture(nullptr),
#endif
_screen(0), _tmpscreen(0),
#ifdef USE_RGB_COLOR
_screenFormat(Graphics::PixelFormat::createFormatCLUT8()),
_cursorFormat(Graphics::PixelFormat::createFormatCLUT8()),
@ -681,12 +685,22 @@ static void fixupResolutionForAspectRatio(AspectRatio desiredAspectRatio, int &w
const int w = width;
const int h = height;
int bestW = 0, bestH = 0;
uint bestMetric = (uint)-1; // Metric is wasted space
#if SDL_VERSION_ATLEAST(2, 0, 0)
const int numModes = SDL_GetNumDisplayModes(0);
SDL_DisplayMode modeData, *mode = &modeData;
for (int i = 0; i < numModes; ++i) {
if (SDL_GetDisplayMode(0, i, &modeData)) {
continue;
}
#else
SDL_Rect const* const*availableModes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_SWSURFACE); //TODO : Maybe specify a pixel format
assert(availableModes);
const SDL_Rect *bestMode = NULL;
uint bestMetric = (uint)-1; // Metric is wasted space
while (const SDL_Rect *mode = *availableModes++) {
#endif
if (mode->w < w)
continue;
if (mode->h < h)
@ -699,15 +713,23 @@ static void fixupResolutionForAspectRatio(AspectRatio desiredAspectRatio, int &w
continue;
bestMetric = metric;
bestMode = mode;
}
bestW = mode->w;
bestH = mode->h;
if (!bestMode) {
// Make editors a bit more happy by having the same amount of closing as
// opening curley braces.
#if SDL_VERSION_ATLEAST(2, 0, 0)
}
#else
}
#endif
if (!bestW || !bestH) {
warning("Unable to enforce the desired aspect ratio");
return;
}
width = bestMode->w;
height = bestMode->h;
width = bestW;
height = bestH;
}
bool SurfaceSdlGraphicsManager::loadGFXMode() {
@ -876,6 +898,10 @@ void SurfaceSdlGraphicsManager::unloadGFXMode() {
_screen = NULL;
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
deinitializeRenderer();
#endif
if (_hwscreen) {
SDL_FreeSurface(_hwscreen);
_hwscreen = NULL;
@ -1443,6 +1469,9 @@ void SurfaceSdlGraphicsManager::setPalette(const byte *colors, uint start, uint
base[i].r = b[0];
base[i].g = b[1];
base[i].b = b[2];
#if SDL_VERSION_ATLEAST(2, 0, 0)
base[i].a = 255;
#endif
}
if (start < _paletteDirtyStart)
@ -1481,6 +1510,9 @@ void SurfaceSdlGraphicsManager::setCursorPalette(const byte *colors, uint start,
base[i].r = b[0];
base[i].g = b[1];
base[i].b = b[2];
#if SDL_VERSION_ATLEAST(2, 0, 0)
base[i].a = 255;
#endif
}
_cursorPaletteDisabled = false;
@ -2317,4 +2349,52 @@ void SurfaceSdlGraphicsManager::notifyMousePos(Common::Point mouse) {
setMousePos(mouse.x, mouse.y);
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
void SurfaceSdlGraphicsManager::deinitializeRenderer() {
SDL_DestroyTexture(_screenTexture);
_screenTexture = nullptr;
SDL_DestroyRenderer(_renderer);
_renderer = nullptr;
destroyWindow();
}
SDL_Surface *SurfaceSdlGraphicsManager::SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) {
deinitializeRenderer();
if (!createWindow(width, height, (flags & SDL_FULLSCREEN) ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)) {
return nullptr;
}
_renderer = SDL_CreateRenderer(_window, -1, 0);
if (!_renderer) {
deinitializeRenderer();
return nullptr;
}
_screenTexture = SDL_CreateTexture(_renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, width, height);
if (!_screenTexture) {
deinitializeRenderer();
return nullptr;
}
SDL_Surface *screen = SDL_CreateRGBSurface(0, width, height, 16, 0xF800, 0x7E0, 0x1F, 0);
if (!screen) {
deinitializeRenderer();
return nullptr;
} else {
return screen;
}
}
void SurfaceSdlGraphicsManager::SDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects) {
SDL_UpdateTexture(_screenTexture, nullptr, screen->pixels, screen->pitch);
SDL_RenderClear(_renderer);
SDL_RenderCopy(_renderer, _screenTexture, NULL, NULL);
SDL_RenderPresent(_renderer);
}
#endif // SDL_VERSION_ATLEAST(2, 0, 0)
#endif

View file

@ -166,6 +166,17 @@ protected:
/** Hardware screen */
SDL_Surface *_hwscreen;
#if SDL_VERSION_ATLEAST(2, 0, 0)
/* SDL2 features a different API for 2D graphics. We create a wrapper
* around this API to keep the code paths as close as possible. */
SDL_Renderer *_renderer;
SDL_Texture *_screenTexture;
void deinitializeRenderer();
SDL_Surface *SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags);
void SDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects);
#endif
/** Unseen game screen */
SDL_Surface *_screen;
#ifdef USE_RGB_COLOR

View file

@ -57,11 +57,13 @@ void SdlMixerManager::init() {
error("Could not initialize SDL: %s", SDL_GetError());
}
#if !SDL_VERSION_ATLEAST(2, 0, 0)
const int maxNameLen = 20;
char sdlDriverName[maxNameLen];
sdlDriverName[0] = '\0';
SDL_AudioDriverName(sdlDriverName, maxNameLen);
debug(1, "Using SDL Audio Driver \"%s\"", sdlDriverName);
#endif
// Get the desired audio specs
SDL_AudioSpec desired = getAudioSpec(SAMPLES_PER_SEC);

View file

@ -74,9 +74,11 @@ MODULE_OBJS += \
# SDL 1.3 removed audio CD support
ifndef USE_SDL13
ifndef USE_SDL2
MODULE_OBJS += \
audiocd/sdl/sdl-audiocd.o
endif
endif
ifdef USE_OPENGL
MODULE_OBJS += \

View file

@ -74,5 +74,50 @@ typedef struct { int FAKE; } FAKE_FILE;
#define strncasecmp FORBIDDEN_SYMBOL_REPLACEMENT
#endif
// SDL 2 has major API changes. We redefine constants which got renamed to
// ease the transition. This is sometimes dangerous because the values changed
// too!
#if SDL_VERSION_ATLEAST(2, 0, 0)
// Type names which changed between SDL 1.2 and SDL 2.
#define SDLKey SDL_Keycode
#define SDLMod SDL_Keymod
#define SDL_keysym SDL_Keysym
// Key code constants which got renamed.
#define SDLK_SCROLLOCK SDLK_SCROLLLOCK
#define SDLK_NUMLOCK SDLK_NUMLOCKCLEAR
#define SDLK_LSUPER SDLK_LGUI
#define SDLK_RSUPER SDLK_RGUI
#define SDLK_PRINT SDLK_PRINTSCREEN
#define SDLK_COMPOSE SDLK_APPLICATION
#define SDLK_KP0 SDLK_KP_0
#define SDLK_KP1 SDLK_KP_1
#define SDLK_KP2 SDLK_KP_2
#define SDLK_KP3 SDLK_KP_3
#define SDLK_KP4 SDLK_KP_4
#define SDLK_KP5 SDLK_KP_5
#define SDLK_KP6 SDLK_KP_6
#define SDLK_KP7 SDLK_KP_7
#define SDLK_KP8 SDLK_KP_8
#define SDLK_KP9 SDLK_KP_9
// Meta key constants which got renamed.
#define KMOD_META KMOD_GUI
// SDL surface flags which got removed.
#define SDL_SRCCOLORKEY 0
#define SDL_SRCALPHA 0
#define SDL_FULLSCREEN 0x40000000
// Compatability implementations for removed functionality.
int SDL_SetColors(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors);
int SDL_SetAlpha(SDL_Surface *surface, Uint32 flag, Uint8 alpha);
#define SDL_SetColorKey SDL_SetColorKey_replacement
int SDL_SetColorKey_replacement(SDL_Surface *surface, Uint32 flag, Uint32 key);
#endif
#endif

View file

@ -126,8 +126,10 @@ void OSystem_SDL::init() {
// Initialize SDL
initSDL();
#if !SDL_VERSION_ATLEAST(2, 0, 0)
// Enable unicode support if possible
SDL_EnableUNICODE(1);
#endif
// Disable OS cursor
SDL_ShowCursor(SDL_DISABLE);
@ -158,10 +160,14 @@ void OSystem_SDL::initBackend() {
// Check if backend has not been initialized
assert(!_inited);
#if SDL_VERSION_ATLEAST(2, 0, 0)
const char *sdlDriverName = SDL_GetCurrentVideoDriver();
#else
const int maxNameLen = 20;
char sdlDriverName[maxNameLen];
sdlDriverName[0] = '\0';
SDL_VideoDriverName(sdlDriverName, maxNameLen);
#endif
// Using printf rather than debug() here as debug()/logging
// is not active by this point.
debug(1, "Using SDL Video Driver \"%s\"", sdlDriverName);
@ -172,6 +178,13 @@ void OSystem_SDL::initBackend() {
_eventSource = new SdlEventSource();
#ifdef USE_OPENGL
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_DisplayMode displayMode;
if (!SDL_GetDesktopDisplayMode(0, &displayMode)) {
_desktopWidth = displayMode.w;
_desktopHeight = displayMode.h;
}
#else
// Query the desktop resolution. We simply hope nothing tried to change
// the resolution so far.
const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
@ -179,6 +192,7 @@ void OSystem_SDL::initBackend() {
_desktopWidth = videoInfo->current_w;
_desktopHeight = videoInfo->current_h;
}
#endif
#endif
if (_graphicsManager == 0) {
@ -681,5 +695,38 @@ void OSystem_SDL::setupGraphicsModes() {
mode++;
}
}
#endif
#if SDL_VERSION_ATLEAST(2, 0, 0)
int SDL_SetColors(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors) {
if (surface->format->palette) {
return !SDL_SetPaletteColors(surface->format->palette, colors, firstcolor, ncolors) ? 1 : 0;
} else {
return 0;
}
}
int SDL_SetAlpha(SDL_Surface *surface, Uint32 flag, Uint8 alpha) {
if (SDL_SetSurfaceAlphaMod(surface, alpha)) {
return -1;
}
if (alpha == 255 || !flag) {
if (SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE)) {
return -1;
}
} else {
if (SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND)) {
return -1;
}
}
return 0;
}
#undef SDL_SetColorKey
int SDL_SetColorKey_replacement(SDL_Surface *surface, Uint32 flag, Uint32 key) {
return SDL_SetColorKey(surface, SDL_TRUE, key) ? -1 : 0;
}
#endif

3
configure vendored
View file

@ -3070,6 +3070,9 @@ case $_backend in
1.3.*)
add_line_to_config_mk "USE_SDL13 = 1"
;;
2.0.*)
add_line_to_config_mk "USE_SDL2 = 1"
;;
*)
;;
esac