Use SDL to create the window

No input nor event loop handling yet, so the window will "stop responding" after a few seconds.

Thanks to KittyCat for the GraphicsWindowSDL2 code.
pull/638/head
scrawl 10 years ago
parent 7a3bc69df7
commit 375b736e74

@ -6,16 +6,15 @@
#include <osgGA/TrackballManipulator>
#include <osgViewer/ViewerEventHandlers>
#include <MyGUI_WidgetManager.h>
#include <SDL.h>
// TODO: move to component
#include <components/misc/rng.hpp>
#include <components/vfs/manager.hpp>
#include <components/vfs/registerarchives.hpp>
#include <components/sdlutil/sdlgraphicswindow.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/texturemanager.hpp>
@ -182,7 +181,8 @@ void OMW::Engine::frame(float frametime)
}
OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
: mEncoding(ToUTF8::WINDOWS_1252)
: mWindow(NULL)
, mEncoding(ToUTF8::WINDOWS_1252)
, mEncoder(NULL)
, mVerboseScripts (false)
, mSkipMenu (false)
@ -219,6 +219,13 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
OMW::Engine::~Engine()
{
mResourceSystem.reset();
mViewer = NULL;
SDL_DestroyWindow(mWindow);
mWindow = NULL;
mEnvironment.cleanup();
delete mScriptContext;
SDL_Quit();
@ -293,24 +300,88 @@ std::string OMW::Engine::loadSettings (Settings::Manager & settings)
return settingspath;
}
void OMW::Engine::prepareEngine (Settings::Manager & settings)
void OMW::Engine::createWindow(Settings::Manager& settings)
{
mEnvironment.setStateManager (
new MWState::StateManager (mCfgMgr.getUserDataPath() / "saves", mContentFiles.at (0)));
int screen = settings.getInt("screen", "Video");
int width = settings.getInt("resolution x", "Video");
int height = settings.getInt("resolution y", "Video");
bool fullscreen = settings.getBool("fullscreen", "Video");
bool windowBorder = settings.getBool("window border", "Video");
bool vsync = settings.getBool("vsync", "Video");
int antialiasing = settings.getInt("antialiasing", "Video");
int pos_x = SDL_WINDOWPOS_CENTERED_DISPLAY(screen),
pos_y = SDL_WINDOWPOS_CENTERED_DISPLAY(screen);
if(fullscreen)
{
pos_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(screen);
pos_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(screen);
}
//OEngine::Render::WindowSettings windowSettings;
//windowSettings.fullscreen = settings.getBool("fullscreen", "Video");
//windowSettings.window_border = settings.getBool("window border", "Video");
//windowSettings.vsync = settings.getBool("vsync", "Video");
//windowSettings.icon = "openmw.png";
//std::string aa = settings.getString("antialiasing", "Video");
//windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0";
Uint32 flags = SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN|SDL_WINDOW_RESIZABLE;
if(fullscreen)
flags |= SDL_WINDOW_FULLSCREEN;
if (!windowBorder)
flags |= SDL_WINDOW_BORDERLESS;
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS,
settings.getBool("minimize on focus loss", "Video") ? "1" : "0");
// not handling fullscreen yet, we should figure this out when adding SDL to the mix
mViewer->setUpViewInWindow(0, 0, settings.getInt("resolution x", "Video"), settings.getInt("resolution y", "Video"), settings.getInt("screen", "Video"));
if (antialiasing > 0)
{
if (SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1) != 0)
std::cerr << "SDL error: " << SDL_GetError() << std::endl;
if (SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, antialiasing) != 0)
std::cerr << "SDL error: " << SDL_GetError() << std::endl;
}
mWindow = SDL_CreateWindow("OpenMW", pos_x, pos_y, width, height, flags);
if (mWindow == NULL)
{
std::cerr << "Failed to create SDL window: " << SDL_GetError() << std::endl;
return;
}
// TODO: set window icon
SDLUtil::setupWindowingSystemInterface();
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
SDL_GetWindowPosition(mWindow, &traits->x, &traits->y);
SDL_GetWindowSize(mWindow, &traits->width, &traits->height);
traits->windowName = SDL_GetWindowTitle(mWindow);
traits->windowDecoration = !(SDL_GetWindowFlags(mWindow)&SDL_WINDOW_BORDERLESS);
traits->screenNum = SDL_GetWindowDisplayIndex(mWindow);
// FIXME: Some way to get these settings back from the SDL window?
traits->red = 8;
traits->green = 8;
traits->blue = 8;
traits->alpha = 8;
traits->depth = 24;
traits->stencil = 8;
traits->vsync = vsync;
traits->doubleBuffer = true;
traits->inheritedWindowData = new SDLUtil::GraphicsWindowSDL2::WindowData(mWindow);
osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
if(!gc.valid()) throw std::runtime_error("Failed to create GraphicsContext");
osg::ref_ptr<osg::Camera> camera = mViewer->getCamera();
camera->setGraphicsContext(gc.get());
camera->setViewport(0, 0, width, height);
mViewer->realize();
}
void OMW::Engine::prepareEngine (Settings::Manager & settings)
{
mEnvironment.setStateManager (
new MWState::StateManager (mCfgMgr.getUserDataPath() / "saves", mContentFiles.at (0)));
createWindow(settings);
osg::ref_ptr<osg::Group> rootNode (new osg::Group);
mViewer->setSceneData(rootNode);

@ -53,11 +53,14 @@ namespace Files
struct ConfigurationManager;
}
struct SDL_Window;
namespace OMW
{
/// \brief Main engine class, that brings together all the components of OpenMW
class Engine
{
SDL_Window* mWindow;
std::auto_ptr<VFS::Manager> mVFS;
std::auto_ptr<Resource::ResourceSystem> mResourceSystem;
MWBase::Environment mEnvironment;
@ -112,6 +115,8 @@ namespace OMW
/// Prepare engine for game play
void prepareEngine (Settings::Manager & settings);
void createWindow(Settings::Manager& settings);
public:
Engine(Files::ConfigurationManager& configurationManager);
virtual ~Engine();

@ -580,16 +580,6 @@ namespace MWClass
return dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData()).mMovement;
}
Ogre::Vector3 Creature::getMovementVector (const MWWorld::Ptr& ptr) const
{
MWMechanics::Movement &movement = getMovementSettings(ptr);
Ogre::Vector3 vec(movement.mPosition);
movement.mPosition[0] = 0.0f;
movement.mPosition[1] = 0.0f;
movement.mPosition[2] = 0.0f;
return vec;
}
Ogre::Vector3 Creature::getRotationVector (const MWWorld::Ptr& ptr) const
{
MWMechanics::Movement &movement = getMovementSettings(ptr);

@ -113,10 +113,6 @@ namespace MWClass
virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const;
///< Return desired movement.
virtual Ogre::Vector3 getMovementVector (const MWWorld::Ptr& ptr) const;
///< Return desired movement vector (determined based on movement settings,
/// stance and stats).
virtual Ogre::Vector3 getRotationVector (const MWWorld::Ptr& ptr) const;
///< Return desired rotations, as euler angles.

@ -961,16 +961,6 @@ namespace MWClass
return dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()).mMovement;
}
Ogre::Vector3 Npc::getMovementVector (const MWWorld::Ptr& ptr) const
{
MWMechanics::Movement &movement = getMovementSettings(ptr);
Ogre::Vector3 vec(movement.mPosition);
movement.mPosition[0] = 0.0f;
movement.mPosition[1] = 0.0f;
movement.mPosition[2] = 0.0f;
return vec;
}
Ogre::Vector3 Npc::getRotationVector (const MWWorld::Ptr& ptr) const
{
MWMechanics::Movement &movement = getMovementSettings(ptr);

@ -105,10 +105,6 @@ namespace MWClass
virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const;
///< Return desired movement.
virtual Ogre::Vector3 getMovementVector (const MWWorld::Ptr& ptr) const;
///< Return desired movement vector (determined based on movement settings,
/// stance and stats).
virtual Ogre::Vector3 getRotationVector (const MWWorld::Ptr& ptr) const;
///< Return desired rotations, as euler angles.

@ -186,11 +186,6 @@ namespace MWWorld
throw std::runtime_error ("movement settings not supported by class");
}
Ogre::Vector3 Class::getMovementVector (const Ptr& ptr) const
{
return Ogre::Vector3 (0, 0, 0);
}
Ogre::Vector3 Class::getRotationVector (const Ptr& ptr) const
{
return Ogre::Vector3 (0, 0, 0);

@ -192,10 +192,6 @@ namespace MWWorld
virtual MWMechanics::Movement& getMovementSettings (const Ptr& ptr) const;
///< Return desired movement.
virtual Ogre::Vector3 getMovementVector (const Ptr& ptr) const;
///< Return desired movement vector (determined based on movement settings,
/// stance and stats).
virtual Ogre::Vector3 getRotationVector (const Ptr& ptr) const;
///< Return desired rotations, as euler angles.

@ -126,6 +126,10 @@ add_component_dir (fontloader
fontloader
)
add_component_dir (sdlutil
sdlgraphicswindow
)
add_component_dir (version
version
)
@ -172,6 +176,7 @@ target_link_libraries(components
${OGRE_LIBRARIES}
${OPENSCENEGRAPH_LIBRARIES}
${BULLET_LIBRARIES}
${SDL2_LIBRARY}
# For MyGUI platform
${OPENGL_gl_LIBRARY}
)

@ -0,0 +1,272 @@
#include "sdlgraphicswindow.hpp"
#include <SDL_video.h>
#include <osg/DeleteHandler>
namespace SDLUtil
{
GraphicsWindowSDL2::~GraphicsWindowSDL2()
{
close(true);
}
bool GraphicsWindowSDL2::setWindowDecorationImplementation(bool flag)
{
if(!mWindow) return false;
SDL_SetWindowBordered(mWindow, flag ? SDL_TRUE : SDL_FALSE);
return true;
}
bool GraphicsWindowSDL2::setWindowRectangleImplementation(int x, int y, int width, int height)
{
if(!mWindow) return false;
SDL_SetWindowPosition(mWindow, x, y);
SDL_SetWindowSize(mWindow, width, height);
return true;
}
void GraphicsWindowSDL2::setWindowName(const std::string &name)
{
if(!mWindow) return;
SDL_SetWindowTitle(mWindow, name.c_str());
_traits->windowName = name;
}
void GraphicsWindowSDL2::setCursor(MouseCursor mouseCursor)
{
_traits->useCursor = false;
}
void GraphicsWindowSDL2::init()
{
if(mValid) return;
if(!_traits.valid())
return;
// getEventQueue()->setCurrentEventState(osgGA::GUIEventAdapter::getAccumulatedEventState().get());
WindowData *inheritedWindowData = dynamic_cast<WindowData*>(_traits->inheritedWindowData.get());
mWindow = inheritedWindowData ? inheritedWindowData->mWindow : NULL;
mOwnsWindow = (mWindow == 0);
if(mOwnsWindow)
{
OSG_NOTICE<<"Error: No SDL window provided."<<std::endl;
return;
}
// SDL will change the current context when it creates a new one, so we
// have to get the current one to be able to restore it afterward.
SDL_Window *oldWin = SDL_GL_GetCurrentWindow();
SDL_GLContext oldCtx = SDL_GL_GetCurrentContext();
mContext = SDL_GL_CreateContext(mWindow);
if(!mContext)
{
OSG_NOTICE<< "Error: Unable to create OpenGL graphics context: "<<SDL_GetError() <<std::endl;
return;
}
setSyncToVBlank(_traits->vsync);
SDL_GL_MakeCurrent(oldWin, oldCtx);
mValid = true;
getEventQueue()->syncWindowRectangleWithGraphcisContext();
}
bool GraphicsWindowSDL2::realizeImplementation()
{
if(mRealized)
{
OSG_NOTICE<< "GraphicsWindowSDL2::realizeImplementation() Already realized" <<std::endl;
return true;
}
if(!mValid) init();
if(!mValid) return false;
SDL_ShowWindow(mWindow);
getEventQueue()->syncWindowRectangleWithGraphcisContext();
mRealized = true;
return true;
}
bool GraphicsWindowSDL2::makeCurrentImplementation()
{
if(!mRealized)
{
OSG_NOTICE<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<<std::endl;
return false;
}
return SDL_GL_MakeCurrent(mWindow, mContext)==0;
}
bool GraphicsWindowSDL2::releaseContextImplementation()
{
if(!mRealized)
{
OSG_NOTICE<< "Warning: GraphicsWindow not realized, cannot do releaseContext." <<std::endl;
return false;
}
return SDL_GL_MakeCurrent(NULL, NULL)==0;
}
void GraphicsWindowSDL2::closeImplementation()
{
// OSG_NOTICE<<"Closing GraphicsWindowSDL2"<<std::endl;
if(mContext)
SDL_GL_DeleteContext(mContext);
mContext = NULL;
if(mWindow && mOwnsWindow)
SDL_DestroyWindow(mWindow);
mWindow = NULL;
mValid = false;
mRealized = false;
}
void GraphicsWindowSDL2::swapBuffersImplementation()
{
if(!mRealized) return;
//OSG_NOTICE<< "swapBuffersImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
SDL_GL_SwapWindow(mWindow);
}
void GraphicsWindowSDL2::setSyncToVBlank(bool on)
{
SDL_GL_SetSwapInterval(on ? 1 : 0);
}
void GraphicsWindowSDL2::raiseWindow()
{
SDL_RaiseWindow(mWindow);
}
class SDL2WindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface
{
public:
SDL2WindowingSystemInterface()
{
OSG_INFO<< "SDL2WindowingSystemInterface()" <<std::endl;
}
virtual ~SDL2WindowingSystemInterface()
{
if(osg::Referenced::getDeleteHandler())
{
osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
osg::Referenced::getDeleteHandler()->flushAll();
}
//OSG_NOTICE<< "~SDL2WindowingSystemInterface()" <<std::endl;
}
virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier&/*si*/)
{
return SDL_GetNumVideoDisplays();
}
virtual void getScreenSettings(const osg::GraphicsContext::ScreenIdentifier &si, osg::GraphicsContext::ScreenSettings &resolution)
{
SDL_DisplayMode mode;
if(SDL_GetCurrentDisplayMode(si.screenNum, &mode) == 0)
{
int bpp = 32;
Uint32 rmask, gmask, bmask, amask;
SDL_PixelFormatEnumToMasks(mode.format, &bpp, &rmask, &gmask, &bmask, &amask);
resolution.width = mode.w;
resolution.height = mode.h;
resolution.colorDepth = bpp;
resolution.refreshRate = mode.refresh_rate;
}
else
{
OSG_NOTICE<< "Unable to query screen \""<<si.screenNum<<"\"." <<std::endl;
resolution.width = 0;
resolution.height = 0;
resolution.colorDepth = 0;
resolution.refreshRate = 0;
}
}
virtual bool setScreenSettings(const osg::GraphicsContext::ScreenIdentifier&/*si*/, const osg::GraphicsContext::ScreenSettings&/*resolution*/)
{
// FIXME: SDL sets a new video mode by having the fullscreen flag on an
// appropriately-sized window, rather than changing it 'raw'.
return false;
}
virtual void enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier &si, osg::GraphicsContext::ScreenSettingsList &resolutionList)
{
osg::GraphicsContext::ScreenSettingsList().swap(resolutionList);
int num_modes = SDL_GetNumDisplayModes(si.screenNum);
resolutionList.reserve(num_modes);
for(int i = 0;i < num_modes;++i)
{
SDL_DisplayMode mode;
if(SDL_GetDisplayMode(si.screenNum, i, &mode) != 0)
{
OSG_NOTICE<< "Failed to get info for display mode "<<i <<std::endl;
continue;
}
int bpp = 32;
Uint32 rmask, gmask, bmask, amask;
if(SDL_PixelFormatEnumToMasks(mode.format, &bpp, &rmask, &gmask, &bmask, &amask) == SDL_FALSE)
{
OSG_NOTICE<< "Failed to get pixel format info for format ID "<<mode.format <<std::endl;
continue;
}
resolutionList.push_back(osg::GraphicsContext::ScreenSettings(mode.w, mode.h, mode.refresh_rate, bpp));
}
if(resolutionList.empty())
{
OSG_NOTICE<< "SDL2WindowingSystemInterface::enumerateScreenSettings() not supported." <<std::endl;
}
}
virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits *traits)
{
// No PBuffer support (you should use FBOs anyway)
if(traits->pbuffer)
return NULL;
osg::ref_ptr<GraphicsWindowSDL2> window = new GraphicsWindowSDL2(traits);
if(window->valid()) return window.release();
return NULL;
}
};
void setupWindowingSystemInterface()
{
osg::GraphicsContext::setWindowingSystemInterface(new SDL2WindowingSystemInterface);
}
} // namespace TK

@ -0,0 +1,108 @@
#ifndef OSGGRAPHICSWINDOW_H
#define OSGGRAPHICSWINDOW_H
#include <SDL.h>
#include <osgViewer/GraphicsWindow>
namespace SDLUtil
{
class GraphicsWindowSDL2 : public osgViewer::GraphicsWindow
{
SDL_Window* mWindow;
SDL_GLContext mContext;
bool mValid;
bool mRealized;
bool mOwnsWindow;
void init();
virtual ~GraphicsWindowSDL2();
public:
GraphicsWindowSDL2(osg::GraphicsContext::Traits *traits)
: mWindow(0)
, mContext(0)
, mValid(false)
, mRealized(false)
, mOwnsWindow(false)
{
_traits = traits;
init();
if(valid())
{
setState(new osg::State);
getState()->setGraphicsContext(this);
if(_traits.valid() && _traits->sharedContext.valid())
{
getState()->setContextID(_traits->sharedContext->getState()->getContextID());
incrementContextIDUsageCount(getState()->getContextID());
}
else
{
getState()->setContextID(osg::GraphicsContext::createNewContextID());
}
}
}
virtual bool isSameKindAs(const Object* object) const { return dynamic_cast<const GraphicsWindowSDL2*>(object)!=0; }
virtual const char* libraryName() const { return "osgViewer"; }
virtual const char* className() const { return "GraphicsWindowSDL2"; }
virtual bool valid() const { return mValid; }
/** Realise the GraphicsContext.*/
virtual bool realizeImplementation();
/** Return true if the graphics context has been realised and is ready to use.*/
virtual bool isRealizedImplementation() const { return mRealized; }
/** Close the graphics context.*/
virtual void closeImplementation();
/** Make this graphics context current.*/
virtual bool makeCurrentImplementation();
/** Release the graphics context.*/
virtual bool releaseContextImplementation();
/** Swap the front and back buffers.*/
virtual void swapBuffersImplementation();
/** Set sync-to-vblank. */
virtual void setSyncToVBlank(bool on);
/** Set Window decoration.*/
virtual bool setWindowDecorationImplementation(bool flag);
/** Raise specified window */
virtual void raiseWindow();
/** Set the window's position and size.*/
virtual bool setWindowRectangleImplementation(int x, int y, int width, int height);
/** Set the name of the window */
virtual void setWindowName(const std::string &name);
/** Set mouse cursor to a specific shape.*/
virtual void setCursor(MouseCursor cursor);
/** WindowData is used to pass in the SDL2 window handle attached the GraphicsContext::Traits structure. */
struct WindowData : public osg::Referenced
{
WindowData(SDL_Window *window) : mWindow(window)
{ }
SDL_Window *mWindow;
};
};
void setupWindowingSystemInterface();
} // namespace TK
#endif /* OSGGRAPHICSWINDOW_H */
Loading…
Cancel
Save