diff --git a/CMakeLists.txt b/CMakeLists.txt index fae7ff6836..d0515a1fb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -458,7 +458,6 @@ endif(WIN32) # Extern add_subdirectory (extern/osg-ffmpeg-videoplayer) add_subdirectory (extern/oics) -#add_subdirectory (extern/sdl4ogre) # Components add_subdirectory (components) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 08d77e7af1..403cb79f28 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -393,7 +393,7 @@ void OMW::Engine::setWindowIcon() else { osg::ref_ptr image = result.getImage(); - SDL_Surface* surface = SDLUtil::imageToSurface(image); + SDL_Surface* surface = SDLUtil::imageToSurface(image, true); SDL_SetWindowIcon(mWindow, surface); SDL_FreeSurface(surface); } diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 9c7a9de20a..5e573c1e4b 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -20,11 +20,12 @@ #include #include -#include +#include #include #include +#include #include @@ -35,6 +36,8 @@ #include #include +#include + #include #include "../mwbase/inputmanager.hpp" @@ -219,7 +222,7 @@ namespace MWGui mLoadingScreen = new LoadingScreen(mResourceSystem->getVFS(), mViewer); //set up the hardware cursor manager - //mCursorManager = new SFO::SDLCursorManager(); + mCursorManager = new SDLUtil::SDLCursorManager(); MyGUI::PointerManager::getInstance().eventChangeMousePointer += MyGUI::newDelegate(this, &WindowManager::onCursorChange); @@ -227,7 +230,7 @@ namespace MWGui onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer()); - //mCursorManager->setEnabled(true); + mCursorManager->setEnabled(true); // hide mygui's pointer MyGUI::PointerManager::getInstance().setVisible(false); @@ -417,7 +420,7 @@ namespace MWGui delete mDebugWindow; delete mJailScreen; - //delete mCursorManager; + delete mCursorManager; cleanupGarbage(); @@ -1152,7 +1155,6 @@ namespace MWGui void WindowManager::onCursorChange(const std::string &name) { - /* if(!mCursorManager->cursorChanged(name)) return; //the cursor manager doesn't want any more info about this cursor //See if we can get the information we need out of the cursor resource @@ -1163,10 +1165,11 @@ namespace MWGui std::string tex_name = imgSet->getIndexInfo(0,0).texture; - Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().getByName(tex_name); + osg::ref_ptr tex = mResourceSystem->getTextureManager()->getTexture2D(tex_name, osg::Texture::CLAMP, osg::Texture::CLAMP); + tex->setUnRefImageDataAfterApply(false); // FIXME? //everything looks good, send it to the cursor manager - if(!tex.isNull()) + if(tex.valid()) { Uint8 size_x = imgSetPtr->getSize().width; Uint8 size_y = imgSetPtr->getSize().height; @@ -1174,10 +1177,9 @@ namespace MWGui Uint8 hotspot_y = imgSetPtr->getHotSpot().top; int rotation = imgSetPtr->getRotation(); - mCursorManager->receiveCursorInfo(name, rotation, tex, size_x, size_y, hotspot_x, hotspot_y); + mCursorManager->receiveCursorInfo(name, rotation, tex->getImage(), size_x, size_y, hotspot_x, hotspot_y); } } - */ } void WindowManager::popGuiMode() diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 3258818896..d07f2fb98d 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -52,9 +52,9 @@ namespace Resource class ResourceSystem; } -namespace SFO +namespace SDLUtil { - class CursorManager; + class SDLCursorManager; } namespace osgMyGUI @@ -454,7 +454,7 @@ namespace MWGui MyGUI::Gui *mGui; // Gui std::vector mGuiModes; - SFO::CursorManager* mCursorManager; + SDLUtil::SDLCursorManager* mCursorManager; std::vector mGarbageDialogs; void cleanupGarbage(); diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 6590c7e995..0c76f666b2 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -127,7 +127,7 @@ add_component_dir (fontloader ) add_component_dir (sdlutil - sdlgraphicswindow imagetosurface sdlinputwrapper OISCompat events + sdlgraphicswindow imagetosurface sdlinputwrapper OISCompat events sdlcursormanager ) add_component_dir (version diff --git a/components/sdlutil/imagetosurface.cpp b/components/sdlutil/imagetosurface.cpp index 36e503c749..6313c0a8fd 100644 --- a/components/sdlutil/imagetosurface.cpp +++ b/components/sdlutil/imagetosurface.cpp @@ -6,7 +6,7 @@ namespace SDLUtil { -SDL_Surface* imageToSurface(osg::Image *image) +SDL_Surface* imageToSurface(osg::Image *image, bool flip) { int width = image->s(); int height = image->t(); @@ -15,7 +15,7 @@ SDL_Surface* imageToSurface(osg::Image *image) for(int x = 0; x < width; ++x) for(int y = 0; y < height; ++y) { - osg::Vec4f clr = image->getColor(x, (height-1)-y); + osg::Vec4f clr = image->getColor(x, flip ? ((height-1)-y) : y); int bpp = surface->format->BytesPerPixel; Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; *(Uint32*)(p) = SDL_MapRGBA(surface->format, static_cast(clr.r() * 255), diff --git a/components/sdlutil/imagetosurface.hpp b/components/sdlutil/imagetosurface.hpp index 2c5df5cbd5..ad0457433c 100644 --- a/components/sdlutil/imagetosurface.hpp +++ b/components/sdlutil/imagetosurface.hpp @@ -13,7 +13,7 @@ namespace SDLUtil /// Convert an osg::Image to an SDL_Surface. /// @note The returned surface must be freed using SDL_FreeSurface. - SDL_Surface* imageToSurface(osg::Image* image); + SDL_Surface* imageToSurface(osg::Image* image, bool flip=false); } diff --git a/components/sdlutil/sdlcursormanager.cpp b/components/sdlutil/sdlcursormanager.cpp new file mode 100644 index 0000000000..b8ae92c578 --- /dev/null +++ b/components/sdlutil/sdlcursormanager.cpp @@ -0,0 +1,182 @@ +#include "sdlcursormanager.hpp" + +#include + +#include +#include + +#include +#include +#include + +#include "imagetosurface.hpp" + +namespace +{ + + class MyGraphicsContext { + public: + MyGraphicsContext(int w, int h) + { + osg::ref_ptr traits = new osg::GraphicsContext::Traits; + traits->x = 0; + traits->y = 0; + traits->width = 1;//w; + traits->height = 1;//h; + traits->windowDecoration = false; + traits->doubleBuffer = false; + traits->sharedContext = 0; + traits->pbuffer = true; + + _gc = osg::GraphicsContext::createGraphicsContext(traits.get()); + + if (!_gc) + { + osg::notify(osg::NOTICE)<<"Failed to create pbuffer, failing back to normal graphics window."<pbuffer = false; + _gc = osg::GraphicsContext::createGraphicsContext(traits.get()); + } + + if (_gc.valid()) + { + _gc->realize(); + _gc->makeCurrent(); + } + } + + osg::ref_ptr getContext() + { + return _gc; + } + + bool valid() const { return _gc.valid() && _gc->isRealized(); } + + private: + osg::ref_ptr _gc; + }; + + osg::ref_ptr decompress (osg::ref_ptr source) + { + int width = source->s(); + int height = source->t(); + + MyGraphicsContext context(width, height); + + osg::ref_ptr state = context.getContext()->getState(); + + osg::ref_ptr texture = new osg::Texture2D; + texture->setImage(source); + + state->applyTextureAttribute(0, texture); + + osg::ref_ptr resultImage = new osg::Image; + resultImage->allocateImage(width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE); + + assert(resultImage->isDataContiguous()); + + // FIXME: implement for GL ES (PBO & glMapBufferRange?) + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, resultImage->data()); + + source->releaseGLObjects(); + texture->releaseGLObjects(); + + return resultImage; + } + +} + +namespace SDLUtil +{ + + SDLCursorManager::SDLCursorManager() : + mEnabled(false), + mInitialized(false) + { + } + + SDLCursorManager::~SDLCursorManager() + { + CursorMap::const_iterator curs_iter = mCursorMap.begin(); + + while(curs_iter != mCursorMap.end()) + { + SDL_FreeCursor(curs_iter->second); + ++curs_iter; + } + + mCursorMap.clear(); + } + + void SDLCursorManager::setEnabled(bool enabled) + { + if(mInitialized && enabled == mEnabled) + return; + + mInitialized = true; + mEnabled = enabled; + + //turn on hardware cursors + if(enabled) + { + _setGUICursor(mCurrentCursor); + } + //turn off hardware cursors + else + { + SDL_ShowCursor(SDL_FALSE); + } + } + + bool SDLCursorManager::cursorChanged(const std::string& name) + { + mCurrentCursor = name; + + CursorMap::const_iterator curs_iter = mCursorMap.find(name); + + //we have this cursor + if(curs_iter != mCursorMap.end()) + { + _setGUICursor(name); + + return false; + } + else + { + //they should get back to us with more info + return true; + } + } + + void SDLCursorManager::_setGUICursor(const std::string &name) + { + SDL_SetCursor(mCursorMap.find(name)->second); + } + + void SDLCursorManager::receiveCursorInfo(const std::string& name, int rotDegrees, osg::Image* image, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y) + { + _createCursorFromResource(name, rotDegrees, image, size_x, size_y, hotspot_x, hotspot_y); + } + + void SDLCursorManager::_createCursorFromResource(const std::string& name, int rotDegrees, osg::Image* image, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y) + { + if (mCursorMap.find(name) != mCursorMap.end()) + return; + + osg::ref_ptr decompressed = decompress(image); + + // TODO: rotate + + SDL_Surface* surf = SDLUtil::imageToSurface(decompressed, false); + + //set the cursor and store it for later + SDL_Cursor* curs = SDL_CreateColorCursor(surf, hotspot_x, hotspot_y); + mCursorMap.insert(CursorMap::value_type(std::string(name), curs)); + + //clean up + SDL_FreeSurface(surf); + + _setGUICursor(name); + } + +} diff --git a/components/sdlutil/sdlcursormanager.hpp b/components/sdlutil/sdlcursormanager.hpp new file mode 100644 index 0000000000..646f548e3c --- /dev/null +++ b/components/sdlutil/sdlcursormanager.hpp @@ -0,0 +1,51 @@ +#ifndef OPENMW_COMPONENTS_SDLUTIL_SDLCURSORMANAGER_H +#define OPENMW_COMPONENTS_SDLUTIL_SDLCURSORMANAGER_H + +#include +#include + +#include + +struct SDL_Cursor; +struct SDL_Surface; + +namespace osg +{ + class Image; +} + +namespace SDLUtil +{ + class SDLCursorManager + { + public: + SDLCursorManager(); + virtual ~SDLCursorManager(); + + /// \brief sets whether to actively manage cursors or not + virtual void setEnabled(bool enabled); + + /// \brief Tell the manager that the cursor has changed, giving the + /// name of the cursor we changed to ("arrow", "ibeam", etc) + /// \return Whether the manager is interested in more information about the cursor + virtual bool cursorChanged(const std::string &name); + + /// \brief Follow up a cursorChanged() call with enough info to create an cursor. + virtual void receiveCursorInfo(const std::string &name, int rotDegrees, osg::Image* image, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y); + + private: + void _createCursorFromResource(const std::string &name, int rotDegrees, osg::Image* image, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y); + void _putPixel(SDL_Surface *surface, int x, int y, Uint32 pixel); + + void _setGUICursor(const std::string& name); + + typedef std::map CursorMap; + CursorMap mCursorMap; + + std::string mCurrentCursor; + bool mEnabled; + bool mInitialized; + }; +} + +#endif diff --git a/components/sdlutil/sdlgraphicswindow.cpp b/components/sdlutil/sdlgraphicswindow.cpp index c69fcca642..f16c0bca4d 100644 --- a/components/sdlutil/sdlgraphicswindow.cpp +++ b/components/sdlutil/sdlgraphicswindow.cpp @@ -102,7 +102,7 @@ void GraphicsWindowSDL2::init() return; } - setSyncToVBlank(_traits->vsync); + SDL_GL_SetSwapInterval(_traits->vsync ? 1 : 0); SDL_GL_MakeCurrent(oldWin, oldCtx); @@ -182,7 +182,14 @@ void GraphicsWindowSDL2::swapBuffersImplementation() void GraphicsWindowSDL2::setSyncToVBlank(bool on) { + SDL_Window *oldWin = SDL_GL_GetCurrentWindow(); + SDL_GLContext oldCtx = SDL_GL_GetCurrentContext(); + + SDL_GL_MakeCurrent(mWindow, mContext); + SDL_GL_SetSwapInterval(on ? 1 : 0); + + SDL_GL_MakeCurrent(oldWin, oldCtx); } void GraphicsWindowSDL2::raiseWindow() diff --git a/components/sdlutil/sdlinputwrapper.cpp b/components/sdlutil/sdlinputwrapper.cpp index 44492cf6c9..eb3370cf7f 100644 --- a/components/sdlutil/sdlinputwrapper.cpp +++ b/components/sdlutil/sdlinputwrapper.cpp @@ -82,10 +82,20 @@ InputWrapper::InputWrapper(SDL_Window* window, osg::ref_ptr v case SDL_KEYDOWN: if (!evt.key.repeat) mKeyboardListener->keyPressed(evt.key); + + // temporary for the stats viewer + if (evt.key.keysym.sym == SDLK_s) + mViewer->getEventQueue()->keyPress('s'); + break; case SDL_KEYUP: if (!evt.key.repeat) mKeyboardListener->keyReleased(evt.key); + + // temporary for the stats viewer + if (evt.key.keysym.sym == SDLK_s) + mViewer->getEventQueue()->keyRelease('s'); + break; case SDL_TEXTINPUT: mKeyboardListener->textInput(evt.text); diff --git a/extern/sdl4ogre/CMakeLists.txt b/extern/sdl4ogre/CMakeLists.txt deleted file mode 100644 index b8c56bd000..0000000000 --- a/extern/sdl4ogre/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -set(SDL4OGRE_LIBRARY "sdl4ogre") - -# Sources - -set(SDL4OGRE_SOURCE_FILES - sdlinputwrapper.cpp - sdlcursormanager.cpp - sdlwindowhelper.cpp - imagerotate.cpp -) - -if (APPLE) - set(SDL4OGRE_SOURCE_FILES ${SDL4OGRE_SOURCE_FILES} osx_utils.mm) -endif () - -set(SDL4OGRE_HEADER_FILES - OISCompat.h - cursormanager.hpp - events.h -) - -add_library(${SDL4OGRE_LIBRARY} STATIC ${SDL4OGRE_SOURCE_FILES} ${SDL4OGRE_HEADER_FILES}) - -link_directories(${CMAKE_CURRENT_BINARY_DIR}) - - -target_link_libraries(${SDL4OGRE_LIBRARY} ${SDL2_LIBRARY}) diff --git a/extern/sdl4ogre/cursormanager.hpp b/extern/sdl4ogre/cursormanager.hpp deleted file mode 100644 index 3036b236be..0000000000 --- a/extern/sdl4ogre/cursormanager.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef SDL4OGRE_CURSOR_MANAGER_H -#define SDL4OGRE_CURSOR_MANAGER_H - -#include -#include - -#include -#include - -namespace SFO -{ -class CursorManager -{ -public: - virtual ~CursorManager(){} - - /// \brief Tell the manager that the cursor has changed, giving the - /// name of the cursor we changed to ("arrow", "ibeam", etc) - /// \return Whether the manager is interested in more information about the cursor - virtual bool cursorChanged(const std::string &name) = 0; - - /// \brief Follow up a cursorChanged() call with enough info to create an cursor. - virtual void receiveCursorInfo(const std::string &name, int rotDegrees, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y) = 0; - - /// \brief sets whether to actively manage cursors or not - virtual void setEnabled(bool enabled) = 0; -}; -} - -#endif diff --git a/extern/sdl4ogre/sdlcursormanager.cpp b/extern/sdl4ogre/sdlcursormanager.cpp deleted file mode 100644 index 61d9c32dd6..0000000000 --- a/extern/sdl4ogre/sdlcursormanager.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include "sdlcursormanager.hpp" - -#include -#include -#include - -#include -#include - -#include "imagerotate.hpp" - -namespace SFO -{ - - SDLCursorManager::SDLCursorManager() : - mEnabled(false), - mInitialized(false) - { - } - - SDLCursorManager::~SDLCursorManager() - { - CursorMap::const_iterator curs_iter = mCursorMap.begin(); - - while(curs_iter != mCursorMap.end()) - { - SDL_FreeCursor(curs_iter->second); - ++curs_iter; - } - - mCursorMap.clear(); - } - - void SDLCursorManager::setEnabled(bool enabled) - { - if(mInitialized && enabled == mEnabled) - return; - - mInitialized = true; - mEnabled = enabled; - - //turn on hardware cursors - if(enabled) - { - _setGUICursor(mCurrentCursor); - } - //turn off hardware cursors - else - { - SDL_ShowCursor(SDL_FALSE); - } - } - - bool SDLCursorManager::cursorChanged(const std::string &name) - { - mCurrentCursor = name; - - CursorMap::const_iterator curs_iter = mCursorMap.find(name); - - //we have this cursor - if(curs_iter != mCursorMap.end()) - { - _setGUICursor(name); - - return false; - } - else - { - //they should get back to us with more info - return true; - } - } - - void SDLCursorManager::_setGUICursor(const std::string &name) - { - SDL_SetCursor(mCursorMap.find(name)->second); - } - - void SDLCursorManager::receiveCursorInfo(const std::string& name, int rotDegrees, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y) - { - _createCursorFromResource(name, rotDegrees, tex, size_x, size_y, hotspot_x, hotspot_y); - } - - /// \brief creates an SDL cursor from an Ogre texture - void SDLCursorManager::_createCursorFromResource(const std::string& name, int rotDegrees, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y) - { - if (mCursorMap.find(name) != mCursorMap.end()) - return; - - std::string tempName = tex->getName() + "_rotated"; - - // we use a render target to uncompress the DDS texture - // just blitting doesn't seem to work on D3D9 - ImageRotate::rotate(tex->getName(), tempName, static_cast(-rotDegrees)); - - Ogre::TexturePtr resultTexture = Ogre::TextureManager::getSingleton().getByName(tempName); - - // now blit to memory - Ogre::Image destImage; - resultTexture->convertToImage(destImage); - - SDL_Surface* surf = SDL_CreateRGBSurface(0,size_x,size_y,32,0xFF000000,0x00FF0000,0x0000FF00,0x000000FF); - - - //copy the Ogre texture to an SDL surface - for(size_t x = 0; x < size_x; ++x) - { - for(size_t y = 0; y < size_y; ++y) - { - Ogre::ColourValue clr = destImage.getColourAt(x, y, 0); - - //set the pixel on the SDL surface to the same value as the Ogre texture's - _putPixel(surf, x, y, SDL_MapRGBA(surf->format, static_cast(clr.r * 255), - static_cast(clr.g * 255), static_cast(clr.b * 255), static_cast(clr.a * 255))); - } - } - - //set the cursor and store it for later - SDL_Cursor* curs = SDL_CreateColorCursor(surf, hotspot_x, hotspot_y); - mCursorMap.insert(CursorMap::value_type(std::string(name), curs)); - - //clean up - SDL_FreeSurface(surf); - Ogre::TextureManager::getSingleton().remove(tempName); - - _setGUICursor(name); - } - - void SDLCursorManager::_putPixel(SDL_Surface *surface, int x, int y, Uint32 pixel) - { - int bpp = surface->format->BytesPerPixel; - /* Here p is the address to the pixel we want to set */ - Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; - - switch(bpp) { - case 1: - *p = pixel; - break; - - case 2: - *(Uint16 *)p = pixel; - break; - - case 3: - if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { - p[0] = (pixel >> 16) & 0xff; - p[1] = (pixel >> 8) & 0xff; - p[2] = pixel & 0xff; - } else { - p[0] = pixel & 0xff; - p[1] = (pixel >> 8) & 0xff; - p[2] = (pixel >> 16) & 0xff; - } - break; - - case 4: - *(Uint32 *)p = pixel; - break; - } - } -} diff --git a/extern/sdl4ogre/sdlcursormanager.hpp b/extern/sdl4ogre/sdlcursormanager.hpp deleted file mode 100644 index 58324fc01c..0000000000 --- a/extern/sdl4ogre/sdlcursormanager.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef SDL4OGRE_CURSORMANAGER_H -#define SDL4OGRE_CURSORMANAGER_H - -#include "cursormanager.hpp" -#include - -struct SDL_Cursor; -struct SDL_Surface; - -namespace SFO -{ - class SDLCursorManager : - public CursorManager - { - public: - SDLCursorManager(); - virtual ~SDLCursorManager(); - - virtual void setEnabled(bool enabled); - - virtual bool cursorChanged(const std::string &name); - virtual void receiveCursorInfo(const std::string &name, int rotDegrees, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y); - - private: - void _createCursorFromResource(const std::string &name, int rotDegrees, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y); - void _putPixel(SDL_Surface *surface, int x, int y, Uint32 pixel); - - void _setGUICursor(const std::string& name); - - typedef std::map CursorMap; - CursorMap mCursorMap; - - std::string mCurrentCursor; - bool mEnabled; - bool mInitialized; - }; -} - -#endif