Files
eepp/src/window/backend/SDL13/cwindowsdl.cpp
spartanj@gmail.com ea34c1faa6 Updated Physics module integrating the lastest changes to Chipmunk Physics 6.
Small fixes to SDL 1.3 version to avoid crashes on Windows.
Avoid to compile SDL 1.2 when compiling SDL 1.3 in Windows.
2011-07-25 00:53:23 -03:00

452 lines
12 KiB
C++

#include "cwindowsdl.hpp"
#ifdef EE_BACKEND_SDL_1_3
#include "cclipboardsdl.hpp"
#include "cinputsdl.hpp"
#include "ccursormanagersdl.hpp"
#include "../../../graphics/cglobalbatchrenderer.hpp"
#include "../../../graphics/cshaderprogrammanager.hpp"
#include "../../../graphics/cvertexbuffermanager.hpp"
#include "../../../graphics/cframebuffermanager.hpp"
#include "../../../graphics/ctexturefactory.hpp"
#include "../../platform/platformimpl.hpp"
namespace EE { namespace Window { namespace Backend { namespace SDL13 {
cWindowSDL::cWindowSDL( WindowSettings Settings, ContextSettings Context ) :
cWindow( Settings, Context, eeNew( cClipboardSDL, ( this ) ), eeNew( cInputSDL, ( this ) ), eeNew( cCursorManagerSDL, ( this ) ) ),
mSDLWindow( NULL ),
mGLContext( NULL )
{
Create( Settings, Context );
}
cWindowSDL::~cWindowSDL() {
}
bool cWindowSDL::Create( WindowSettings Settings, ContextSettings Context ) {
try {
if ( mWindow.Created )
return false;
mWindow.WindowConfig = Settings;
mWindow.ContextConfig = Context;
if ( SDL_Init( SDL_INIT_VIDEO ) != 0 ) {
cLog::instance()->Write( "Unable to initialize SDL: " + std::string( SDL_GetError() ) );
return false;
}
SDL_DisplayMode dpm;
SDL_GetDesktopDisplayMode( 0, &dpm );
mWindow.DesktopResolution = eeSize( dpm.w, dpm.h );
if ( mWindow.WindowConfig.Style & WindowStyle::UseDesktopResolution ) {
mWindow.WindowConfig.Width = mWindow.DesktopResolution.Width();
mWindow.WindowConfig.Height = mWindow.DesktopResolution.Height();
}
mWindow.Flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
if ( mWindow.WindowConfig.Style & WindowStyle::Resize ) {
mWindow.Flags |= SDL_WINDOW_RESIZABLE;
}
if ( mWindow.WindowConfig.Style & WindowStyle::NoBorder ) {
mWindow.Flags |= SDL_WINDOW_BORDERLESS;
}
SetGLConfig();
Uint32 mTmpFlags = mWindow.Flags;
if ( mWindow.WindowConfig.Style & WindowStyle::Fullscreen ) {
mTmpFlags |= SDL_WINDOW_FULLSCREEN;
}
mSDLWindow = SDL_CreateWindow( mWindow.WindowConfig.Caption.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, mWindow.WindowConfig.Width, mWindow.WindowConfig.Height, mTmpFlags );
mWindow.WindowSize = eeSize( mWindow.WindowConfig.Width, mWindow.WindowConfig.Height );
if ( NULL == mSDLWindow ) {
cLog::instance()->Write( "Unable to create window: " + std::string( SDL_GetError() ) );
return false;
}
mGLContext = SDL_GL_CreateContext( mSDLWindow );
if ( NULL == mGLContext ) {
cLog::instance()->Write( "Unable to create context: " + std::string( SDL_GetError() ) );
return false;
}
SDL_GL_SetSwapInterval( ( mWindow.ContextConfig.VSync ? 1 : 0 ) ); // VSync
if ( NULL == cGL::ExistsSingleton() ) {
cGL::CreateSingleton( mWindow.ContextConfig.Version );
cGL::instance()->Init();
}
CreatePlatform();
GetMainContext();
Caption( mWindow.WindowConfig.Caption );
CreateView();
Setup2D();
mWindow.Created = true;
if ( "" != mWindow.WindowConfig.Icon ) {
Icon( mWindow.WindowConfig.Icon );
}
LogSuccessfulInit( GetVersion() );
/// Init the clipboard after the window creation
reinterpret_cast<cClipboardSDL*> ( mClipboard )->Init();
/// Init the input after the window creation
reinterpret_cast<cInputSDL*> ( mInput )->Init();
mCursorManager->Set( Cursor::SYS_CURSOR_DEFAULT );
return true;
} catch (...) {
LogFailureInit( "cWindowSDL", GetVersion() );
return false;
}
}
std::string cWindowSDL::GetVersion() {
SDL_version ver;
SDL_GetVersion( &ver );
return StrFormated( "SDL %d.%d.%d", ver.major, ver.minor, ver.patch );
}
void cWindowSDL::CreatePlatform() {
eeSAFE_DELETE( mPlatform );
#if EE_PLATFORM == EE_PLATFORM_WIN || EE_PLATFORM == EE_PLATFORM_MACOSX || defined( EE_X11_PLATFORM )
SDL_VERSION( &mWMinfo.version );
SDL_GetWindowWMInfo ( mSDLWindow, &mWMinfo );
#endif
#if defined( EE_X11_PLATFORM )
mPlatform = eeNew( Platform::cX11Impl, ( this, mWMinfo.info.x11.display, mWMinfo.info.x11.window, mWMinfo.info.x11.window, NULL, NULL ) );
#elif EE_PLATFORM == EE_PLATFORM_WIN
mPlatform = eeNew( Platform::cWinImpl, ( this, GetWindowHandler() ) );
#elif EE_PLATFORM == EE_PLATFORM_MACOSX
mPlatform = eeNew( Platform::cOSXImpl, ( this ) );
#else
cWindow::CreatePlatform();
#endif
}
void cWindowSDL::SetGLConfig() {
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE , mWindow.ContextConfig.DepthBufferSize ); // Depth
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, ( mWindow.ContextConfig.DoubleBuffering ? 1 : 0 ) ); // Double Buffering
SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, mWindow.ContextConfig.StencilBufferSize );
if ( mWindow.WindowConfig.BitsPerPixel == 16 ) {
SDL_GL_SetAttribute( SDL_GL_RED_SIZE , 4 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE , 4 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE , 4 );
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE , 4 );
} else {
SDL_GL_SetAttribute( SDL_GL_RED_SIZE , 8);
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE , 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE , 8 );
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE , 8 );
}
}
void cWindowSDL::ToggleFullscreen() {
bool WasMaximized = mWindow.Maximized;
if ( Windowed() ) {
Size( mWindow.WindowConfig.Width, mWindow.WindowConfig.Height, !Windowed() );
} else {
Size( mWindow.WindowSize.Width(), mWindow.WindowSize.Height(), !Windowed() );
}
if ( WasMaximized ) {
Maximize();
}
GetCursorManager()->Reload();
}
void cWindowSDL::Caption( const std::string& Caption ) {
mWindow.WindowConfig.Caption = Caption;
SDL_SetWindowTitle( mSDLWindow, Caption.c_str() );
}
bool cWindowSDL::Active() {
Uint32 flags = 0;
flags = SDL_GetWindowFlags( mSDLWindow );
return 0 != ( ( flags & SDL_WINDOW_INPUT_FOCUS ) && ( flags & SDL_WINDOW_MOUSE_FOCUS ) );
}
bool cWindowSDL::Visible() {
Uint32 flags = 0;
flags = SDL_GetWindowFlags( mSDLWindow );
return 0 != ( ( flags & SDL_WINDOW_SHOWN ) && !( flags & SDL_WINDOW_MINIMIZED ) );
}
void cWindowSDL::Size( Uint32 Width, Uint32 Height, bool Windowed ) {
if ( ( !Width || !Height ) ) {
Width = mWindow.DesktopResolution.Width();
Height = mWindow.DesktopResolution.Height();
}
if ( this->Windowed() == Windowed && Width == mWindow.WindowConfig.Width && Height == mWindow.WindowConfig.Height )
return;
try {
cLog::instance()->Writef( "Switching from %s to %s. Width: %d Height %d.", this->Windowed() ? "windowed" : "fullscreen", Windowed ? "windowed" : "fullscreen", Width, Height );
#if EE_PLATFORM == EE_PLATFORM_WIN || EE_PLATFORM == EE_PLATFORM_MACOSX
#if EE_PLATFORM == EE_PLATFORM_WIN
bool Reload = this->Windowed() != Windowed;
#else
bool Reload = true;
#endif
if ( Reload )
Graphics::cTextureFactory::instance()->GrabTextures();
#endif
Uint32 oldWidth = mWindow.WindowConfig.Width;
Uint32 oldHeight = mWindow.WindowConfig.Height;
mWindow.WindowConfig.Width = Width;
mWindow.WindowConfig.Height = Height;
if ( Windowed ) {
mWindow.WindowSize = eeSize( Width, Height );
} else {
mWindow.WindowSize = eeSize( oldWidth, oldHeight );
}
if ( this->Windowed() && !Windowed ) {
mWinPos = Position();
} else {
SDL_SetWindowFullscreen( mSDLWindow, Windowed ? SDL_FALSE : SDL_TRUE );
}
SDL_SetWindowSize( mSDLWindow, Width, Height );
if ( this->Windowed() && !Windowed ) {
mWinPos = Position();
SetGLConfig();
SDL_SetWindowFullscreen( mSDLWindow, Windowed ? SDL_FALSE : SDL_TRUE );
}
#if EE_PLATFORM == EE_PLATFORM_WIN || EE_PLATFORM == EE_PLATFORM_MACOSX
if ( Reload ) {
cGL::instance()->Init();
Graphics::cTextureFactory::instance()->UngrabTextures(); // Reload all textures
Graphics::cShaderProgramManager::instance()->Reload(); // Reload all shaders
Graphics::Private::cFrameBufferManager::instance()->Reload(); // Reload all frame buffers
Graphics::Private::cVertexBufferManager::instance()->Reload(); // Reload all vertex buffers
GetMainContext(); // Recover the context
CreatePlatform();
}
#endif
if ( !this->Windowed() && Windowed ) {
Position( mWinPos.x, mWinPos.y );
}
SetFlagValue( &mWindow.WindowConfig.Style, WindowStyle::Fullscreen, !Windowed );
mDefaultView.SetView( 0, 0, Width, Height );
Setup2D();
SendVideoResizeCb();
mCursorManager->Reload();
SDL_PumpEvents();
SDL_FlushEvent( SDL_WINDOWEVENT );
} catch (...) {
cLog::instance()->Write( "Unable to change resolution: " + std::string( SDL_GetError() ) );
cLog::instance()->Save();
mWindow.Created = false;
}
}
void cWindowSDL::SwapBuffers() {
SDL_GL_SwapWindow( mSDLWindow );
}
std::vector< std::pair<unsigned int, unsigned int> > cWindowSDL::GetPossibleResolutions() const {
std::vector< std::pair<unsigned int, unsigned int> > result;
for ( Int32 i = 0; i < SDL_GetNumDisplayModes(0); i++ ) {
SDL_DisplayMode mode;
SDL_GetDisplayMode( 0, i, &mode );
result.push_back( std::pair<unsigned int, unsigned int>( mode.w, mode.h ) );
}
return result;
}
void cWindowSDL::SetGamma( eeFloat Red, eeFloat Green, eeFloat Blue ) {
eeclamp( &Red , 0.1f, 10.0f );
eeclamp( &Green , 0.1f, 10.0f );
eeclamp( &Blue , 0.1f, 10.0f );
Uint16 red_ramp[256];
Uint16 green_ramp[256];
Uint16 blue_ramp[256];
SDL_CalculateGammaRamp(Red, red_ramp);
if (Green == Red) {
SDL_memcpy(green_ramp, red_ramp, sizeof(red_ramp));
} else {
SDL_CalculateGammaRamp(Green, green_ramp);
}
if (Blue == Red) {
SDL_memcpy(blue_ramp, red_ramp, sizeof(red_ramp));
} else {
SDL_CalculateGammaRamp(Blue, blue_ramp);
}
SDL_SetWindowGammaRamp( mSDLWindow, red_ramp, green_ramp, blue_ramp );
}
eeWindowHandler cWindowSDL::GetWindowHandler() {
#if EE_PLATFORM == EE_PLATFORM_WIN
return mWMinfo.info.win.window;
#elif defined( EE_X11_PLATFORM )
return mWMinfo.info.x11.display;
#elif EE_PLATFORM == EE_PLATFORM_MACOSX
return mWMinfo.info.cocoa.window;
#else
return 0;
#endif
}
bool cWindowSDL::Icon( const std::string& Path ) {
int x, y, c;
if ( !FileExists( Path ) ) {
return false;
}
if ( !mWindow.Created ) {
if ( stbi_info( Path.c_str(), &x, &y, &c ) ) {
mWindow.WindowConfig.Icon = Path;
return true;
}
return false;
}
unsigned char * Ptr = stbi_load( Path.c_str(), &x, &y, &c, 0 );
if ( NULL != Ptr ) {
Int32 W = x;
Int32 H = y;
if ( ( W % 8 ) == 0 && ( H % 8 ) == 0 ) {
Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
SDL_Surface * TempGlyphSheet = SDL_CreateRGBSurface(SDL_SWSURFACE, W, H, c * 8, rmask, gmask, bmask, amask);
SDL_LockSurface( TempGlyphSheet );
Uint32 ssize = TempGlyphSheet->w * TempGlyphSheet->h * c;
for ( Uint32 i=0; i < ssize; i++ ) {
( static_cast<Uint8*>( TempGlyphSheet->pixels ) )[i+0] = (Ptr)[i];
}
SDL_UnlockSurface( TempGlyphSheet );
SDL_SetWindowIcon( mSDLWindow, TempGlyphSheet );
SDL_FreeSurface( TempGlyphSheet );
free( Ptr );
return true;
}
free( Ptr );
}
return false;
}
void cWindowSDL::Minimize() {
SDL_MinimizeWindow( mSDLWindow );
}
void cWindowSDL::Maximize() {
SDL_MaximizeWindow( mSDLWindow );
}
void cWindowSDL::Hide() {
SDL_HideWindow( mSDLWindow );
}
void cWindowSDL::Raise() {
SDL_RaiseWindow( mSDLWindow );
}
void cWindowSDL::Show() {
SDL_ShowWindow( mSDLWindow );
}
void cWindowSDL::Position( Int16 Left, Int16 Top ) {
SDL_SetWindowPosition( mSDLWindow, Left, Top );
}
eeVector2i cWindowSDL::Position() {
eeVector2i p;
SDL_GetWindowPosition( mSDLWindow, &p.x, &p.y );
return p;
}
SDL_WindowID cWindowSDL::GetSDLWindow() const {
return mSDLWindow;
}
}}}}
#endif