You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw-tes3mp/extern/sdl4ogre/sdlwindowhelper.cpp

131 lines
3.6 KiB
C++

#include "sdlwindowhelper.hpp"
#include <OgreStringConverter.h>
#include <OgreRoot.h>
#include <OgreTextureManager.h>
#include <SDL_syswm.h>
#include <SDL_endian.h>
#include <stdexcept>
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
#include "osx_utils.h"
#endif
namespace SFO
{
SDLWindowHelper::SDLWindowHelper (SDL_Window* window, int w, int h,
const std::string& title, bool fullscreen, Ogre::NameValuePairList params)
: mSDLWindow(window)
{
//get the native whnd
struct SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
if (SDL_GetWindowWMInfo(mSDLWindow, &wmInfo) == SDL_FALSE)
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((uintptr_t)wmInfo.info.win.window);
break;
#elif __MACOSX__
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(WindowContentViewHandle(wmInfo));
break;
#elif ANDROID
case SDL_SYSWM_ANDROID:
winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.android.window);
break;
#else
case SDL_SYSWM_X11:
winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.x11.window);
break;
#endif
default:
throw std::runtime_error("Unexpected WM!");
break;
}
/// \todo externalWindowHandle is deprecated according to the source code. Figure out a way to get parentWindowHandle
/// to work properly. On Linux/X11 it causes an occasional GLXBadDrawable error.
#ifdef ANDROID
SDL_GLContext context= SDL_GL_CreateContext(window);
params.insert(std::make_pair("currentGLContext","True"));
#endif
params.insert(std::make_pair("externalWindowHandle", winHandle));
mWindow = Ogre::Root::getSingleton().createRenderWindow(title, w, h, fullscreen, &params);
}
void SDLWindowHelper::setWindowIcon(const std::string &name)
{
Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().load(name, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME);
if (texture.isNull())
{
std::stringstream error;
error << "Window icon not found: " << name;
throw std::runtime_error(error.str());
}
Ogre::Image image;
texture->convertToImage(image);
SDL_Surface* surface = SDL_CreateRGBSurface(0,texture->getWidth(),texture->getHeight(),32,0xFF000000,0x00FF0000,0x0000FF00,0x000000FF);
//copy the Ogre texture to an SDL surface
for(size_t x = 0; x < texture->getWidth(); ++x)
{
for(size_t y = 0; y < texture->getHeight(); ++y)
{
Ogre::ColourValue clr = image.getColourAt(x, y, 0);
//set the pixel on the SDL surface to the same value as the Ogre texture's
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;
Uint32 pixel = SDL_MapRGBA(surface->format, static_cast<Uint8>(clr.r * 255),
static_cast<Uint8>(clr.g * 255), static_cast<Uint8>(clr.b * 255), static_cast<Uint8>(clr.a * 255));
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;
}
}
}
SDL_SetWindowIcon(mSDLWindow, surface);
SDL_FreeSurface(surface);
}
}