Have SDL manage the window instead of OGRE to work around SDL Windows bugs (grumble)

actorid
Jordan Milne 12 years ago
parent d26e33eb26
commit 043e29c620

@ -1,7 +1,5 @@
#include "engine.hpp"
#include <SDL.h>
#include "components/esm/loadcell.hpp"
#include <OgreRoot.h>
@ -40,6 +38,7 @@
#include "mwmechanics/mechanicsmanagerimp.hpp"
#include <SDL.h>
void OMW::Engine::executeLocalScripts()
{
@ -70,6 +69,8 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
{
try
{
handleSDLMessages();
mEnvironment.setFrameDuration (evt.timeSinceLastFrame);
// update input
@ -116,6 +117,9 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(), tri, batch);
MWBase::Environment::get().getWindowManager()->onFrame(evt.timeSinceLastFrame);
//Flush any events that weren't handled this frame
SDL_FlushEvents(0x0, 0xFFFFFFFF);
}
catch (const std::exception& e)
{
@ -125,6 +129,65 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
return true;
}
void OMW::Engine::handleSDLMessages()
{
//Pump messages since the last frame
const int max_events = 20;
SDL_Event events[max_events];
SDL_PumpEvents();
int num_events = SDL_PeepEvents(events, max_events, SDL_PEEKEVENT, SDL_WINDOWEVENT, SDL_WINDOWEVENT);
bool move_or_resize = false;
unsigned int size_x = 0;
unsigned int size_y = 0;
if(num_events != 0)
{
for(int i=0; i < num_events; ++i)
{
switch(events[i].window.event)
{
case SDL_WINDOWEVENT_RESIZED:
case SDL_WINDOWEVENT_MOVED:
printf("Resizing window!\n");
move_or_resize = true;
size_x = events[i].window.data1;
size_y = events[i].window.data2;
break;
}
}
}
//handle window movements
if(move_or_resize)
{
mOgre->adjustViewport();
if(!mOgre->getWindow()->isFullScreen())
{
SDL_DisplayMode dispMode;
SDL_Window* sdlWindow = mOgre->getSDLWindow();
SDL_GetWindowDisplayMode(sdlWindow, &dispMode);
dispMode.w = size_x;
dispMode.h = size_y;
SDL_SetWindowDisplayMode(sdlWindow, &dispMode);
mOgre->getWindow()->windowMovedOrResized();
mOgre->getWindow()->resize(size_x, size_y);
}
}
if(SDL_PeepEvents(NULL, 1, SDL_PEEKEVENT, SDL_QUIT, SDL_QUIT) != 0)
{
//user requested a quit, break out.
mOgre->getRoot()->queueEndRendering();
}
}
OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
: mOgre (0)
, mFpsLevel(0)
@ -140,6 +203,16 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
{
std::srand ( std::time(NULL) );
MWClass::registerClasses();
Uint32 flags = SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE;
if(SDL_WasInit(flags) == 0)
{
//kindly ask SDL not to trash our OGL context
//might this be related to http://bugzilla.libsdl.org/show_bug.cgi?id=748 ?
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
if(SDL_Init(flags) != 0)
throw std::runtime_error("Couldn't initialize SDL!");
}
}
OMW::Engine::~Engine()
@ -147,6 +220,7 @@ OMW::Engine::~Engine()
mEnvironment.cleanup();
delete mScriptContext;
delete mOgre;
SDL_Quit();
}
// Load all BSA files in data directory.
@ -317,7 +391,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
addResourcesDirectory(mResDir / "shadows");
addZipResource(mResDir / "mygui" / "Obliviontt.zip");
// Create the window
OEngine::Render::WindowSettings windowSettings;
windowSettings.fullscreen = settings.getBool("fullscreen", "Video");
windowSettings.window_x = settings.getInt("resolution x", "Video");
@ -325,20 +398,11 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
windowSettings.vsync = settings.getBool("vsync", "Video");
std::string aa = settings.getString("antialiasing", "Video");
windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0";
mOgre->createWindow("OpenMW", windowSettings);
loadBSA();
Uint32 flags = SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE;
if(SDL_WasInit(flags) == 0)
{
//kindly ask SDL not to trash our OGL context
//might this be related to http://bugzilla.libsdl.org/show_bug.cgi?id=748 ?
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
if(SDL_Init(flags) != 0)
throw std::runtime_error("Couldn't initialize SDL!");
}
// cursor replacer (converts the cursor from the bsa so they can be used by mygui)
MWGui::CursorReplace replacer;

@ -103,6 +103,8 @@ namespace OMW
void executeLocalScripts();
void handleSDLMessages();
virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt);
/// Load settings from various files, returns the path to the user settings file

@ -85,7 +85,6 @@ namespace SFO
mSDLWindow = NULL;
SDL_StopTextInput();
SDL_Quit();
}
void InputWrapper::capture()
@ -121,24 +120,6 @@ namespace SFO
case SDL_KEYUP:
mKeyboardListener->keyReleased(evt.key);
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
mWindowListener->windowFocusChange(true);
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
mWindowListener->windowFocusChange(false);
break;
case SDL_WINDOWEVENT_EXPOSED:
mWindowListener->windowVisibilityChange(true);
break;
case SDL_WINDOWEVENT_HIDDEN:
mWindowListener->windowVisibilityChange(false);
break;
//SDL traps ^C signals, pass it to OGRE.
case SDL_QUIT:
Ogre::Root::getSingleton().queueEndRendering();
break;
}
}
}
@ -186,9 +167,7 @@ namespace SFO
//now remove all mouse events using the old setting from the queue
SDL_PumpEvents();
SDL_Event dummy[20];
SDL_PeepEvents(dummy, 20, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION);
SDL_FlushEvent(SDL_MOUSEMOTION);
}
/// \brief Internal method for ignoring relative motions as a side effect

@ -1,6 +1,9 @@
#include "renderer.hpp"
#include "fader.hpp"
#include <SDL.h>
#include <SDL_syswm.h>
#include "OgreRoot.h"
#include "OgreRenderWindow.h"
#include "OgreLogManager.h"
@ -47,11 +50,16 @@ void OgreRenderer::cleanup()
delete mRoot;
mRoot = NULL;
SDL_DestroyWindow(mSDLWindow);
mSDLWindow = NULL;
unloadPlugins();
}
void OgreRenderer::start()
{
//TODO: Check if we still need to do this if we're using SDL's
//message pump
#if defined(__APPLE__) && !defined(__LP64__)
// OSX Carbon Message Pump
do {
@ -214,6 +222,56 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings&
params.insert(std::make_pair("FSAA", settings.fsaa));
params.insert(std::make_pair("vsync", settings.vsync ? "true" : "false"));
// Create an application window with the following settings:
SDL_Window *window = SDL_CreateWindow(
"OpenMW", // window title
SDL_WINDOWPOS_UNDEFINED, // initial x position
SDL_WINDOWPOS_UNDEFINED, // initial y position
settings.window_x, // width, in pixels
settings.window_y, // height, in pixels
SDL_WINDOW_SHOWN|SDL_WINDOW_RESIZABLE
| (settings.fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)
);
//get the native whnd
struct SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
if(-1 == SDL_GetWindowWMInfo(window, &wmInfo))
throw std::runtime_error("Couldn't get WM Info!");
Ogre::String winHandle;
switch(wmInfo.subsystem)
{
#ifdef WIN32
case SDL_SYSWM_WINDOWS:
// Windows code
winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.win.window);
break;
#elif MACOS
case SDL_SYSWM_COCOA:
//required to make OGRE play nice with our window
params.insert(std::make_pair("macAPI", "cocoa"));
params.insert(std::make_pair("macAPICocoaUseNSView", "true"));
winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.cocoa.window);
break;
#else
case SDL_SYSWM_X11:
winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.x11.display);
winHandle += ":0:";
winHandle += Ogre::StringConverter::toString((unsigned long)wmInfo.info.x11.window);
break;
#endif
default:
throw std::runtime_error("Unexpected WM!");
break;
}
params.insert(std::make_pair("externalWindowHandle", winHandle));
mWindow = mRoot->createRenderWindow(title, settings.window_x, settings.window_y, settings.fullscreen, &params);
// create the semi-transparent black background texture used by the GUI.
@ -253,7 +311,11 @@ void OgreRenderer::createScene(const std::string& camName, float fov, float near
void OgreRenderer::adjustViewport()
{
// Alter the camera aspect ratio to match the viewport
mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight()));
if(mCamera != NULL)
{
mView->setDimensions(0, 0, 1, 1);
mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight()));
}
}
void OgreRenderer::setWindowEventListener(Ogre::WindowEventListener* listener)

@ -31,6 +31,8 @@
#include <OgreRoot.h>
#endif
struct SDL_Window;
namespace Ogre
{
#if !defined(__APPLE__) || defined(__LP64__)
@ -74,6 +76,7 @@ namespace OEngine
Ogre::Root *mRoot;
#endif
Ogre::RenderWindow *mWindow;
SDL_Window *mSDLWindow;
Ogre::SceneManager *mScene;
Ogre::Camera *mCamera;
Ogre::Viewport *mView;
@ -99,6 +102,7 @@ namespace OEngine
OgreRenderer()
: mRoot(NULL)
, mWindow(NULL)
, mSDLWindow(NULL)
, mScene(NULL)
, mCamera(NULL)
, mView(NULL)
@ -169,6 +173,9 @@ namespace OEngine
/// Get the rendering window
Ogre::RenderWindow *getWindow() { return mWindow; }
/// Get the SDL Window
SDL_Window *getSDLWindow() { return mSDLWindow; }
/// Get the scene manager
Ogre::SceneManager *getScene() { return mScene; }

Loading…
Cancel
Save