From 428d560a6bf75d818811d3badef1a7ea13fb218c Mon Sep 17 00:00:00 2001 From: Chris Danford Date: Thu, 5 Jun 2003 19:29:27 +0000 Subject: [PATCH] Clean up resolution fallback logic Add video settings for G400 Working on composited text --- stepmania/src/CompositedText.cpp | 108 ++++++++++++++++++ stepmania/src/CompositedText.h | 22 ++++ stepmania/src/CourseContentsList.h | 1 - stepmania/src/Font.cpp | 103 ++++++++++------- stepmania/src/Font.h | 7 ++ stepmania/src/JukeboxMenu.h | 2 +- stepmania/src/NoteDisplay.cpp | 3 +- stepmania/src/PrefsManager.cpp | 17 ++- stepmania/src/PrefsManager.h | 6 +- stepmania/src/RageBitmapTexture.cpp | 17 ++- stepmania/src/RageDisplay.cpp | 47 ++++++++ stepmania/src/RageDisplay.h | 58 ++++++++-- stepmania/src/RageDisplay_D3D.cpp | 104 +++++------------ stepmania/src/RageDisplay_D3D.h | 9 +- stepmania/src/RageDisplay_OGL.cpp | 66 +++++------ stepmania/src/RageDisplay_OGL.h | 9 +- stepmania/src/RageMath.cpp | 4 +- stepmania/src/RageTexture.cpp | 23 ++-- stepmania/src/RageTexture.h | 4 +- stepmania/src/SDL_utils.cpp | 63 ++++++++++ stepmania/src/SDL_utils.h | 6 + stepmania/src/ScreenSandbox.cpp | 9 +- stepmania/src/ScreenSandbox.h | 1 + stepmania/src/StepMania.cpp | 99 ++++++++-------- stepmania/src/StepMania.dsp | 27 ++++- stepmania/src/StepMania.vcproj | 6 + stepmania/src/TextBanner.cpp | 8 ++ stepmania/src/TextBanner.h | 1 + .../src/arch/LowLevelWindow/LowLevelWindow.h | 15 +-- .../LowLevelWindow/LowLevelWindow_SDL.cpp | 57 ++++----- .../arch/LowLevelWindow/LowLevelWindow_SDL.h | 10 +- 31 files changed, 602 insertions(+), 310 deletions(-) create mode 100644 stepmania/src/CompositedText.cpp create mode 100644 stepmania/src/CompositedText.h diff --git a/stepmania/src/CompositedText.cpp b/stepmania/src/CompositedText.cpp new file mode 100644 index 0000000000..5ae472282a --- /dev/null +++ b/stepmania/src/CompositedText.cpp @@ -0,0 +1,108 @@ +#include "global.h" +/* +----------------------------------------------------------------------------- + Class: CompositedText + + Desc: See header. + + Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. + Chris Danford +----------------------------------------------------------------------------- +*/ + +#include "CompositedText.h" +#include "Font.h" +#include "FontManager.h" +#include "RageDisplay.h" +#include "Actor.h" +#include "SDL_video.h" +#include "SDL_utils.h" + + +SDL_Surface* CreateCompositedText( CString sFontFile, CString sText ) +{ + // build a font texture + Font* pFont = FONT->LoadFont( sFontFile ); + + vector asTextLines; + split(CStringToWstring(sText), L"\n", asTextLines, false); + + /* calculate line lengths and widths */ + vector LineWidths; + int iWidestLineWidth = 0; + for( unsigned l=0; lGetLineWidthInSourcePixels( asTextLines[l] )); + iWidestLineWidth = max(iWidestLineWidth, LineWidths.back()); + } + + int TotalHeight = pFont->GetHeight() * asTextLines.size(); + unsigned i; + int MinSpacing = 0; + + /* The height (from the origin to the baseline): */ + int Padding = max(pFont->GetLineSpacing(), MinSpacing) - pFont->GetHeight(); + + /* There's padding between every line: */ + TotalHeight += Padding * (asTextLines.size()-1); + + + /* Because of the "draw extra pixels" and the fact that frame height is often + * greater than the line spacing, we need to add some padding around all edges. + * Is there a more elegant way we could be handling this? */ + const int PADDING = 32; + int imageWidth = iWidestLineWidth+PADDING; + int imageHeight = TotalHeight+PADDING; + + /* Make sure the image size is even to maintain pixel/texel alignment. */ + if( imageWidth%2==1 ) imageWidth++; + if( imageHeight%2==1 ) imageHeight++; + + /* Allocate surface */ + PixelFormat pixfmt = FMT_RGBA8; + const PixelFormatDesc *pfd = DISPLAY->GetPixelFormatDesc(pixfmt); + SDL_Surface *img = SDL_CreateRGBSurfaceSane(SDL_SWSURFACE, imageWidth, imageHeight, + pfd->bpp, pfd->masks[0], pfd->masks[1], pfd->masks[2], pfd->masks[3]); + SDL_FillRect( img, NULL, 0x00000000 ); + + + int iY = PADDING/2; + + for( i=0; iGetHeight(); + const wstring &sLine = asTextLines[i]; + const int iLineWidth = LineWidths[i]; + + int iX = PADDING/2; + + for( unsigned j=0; jGetGlyph( sLine[j] ); + + SDL_Rect blitSrc; + blitSrc.x = g.blitSrc.left; + blitSrc.w = g.blitSrc.right - g.blitSrc.left; + blitSrc.y = g.blitSrc.top; + blitSrc.h = g.blitSrc.bottom - g.blitSrc.top; + + SDL_Rect blitDst; + blitDst.x = iX+g.hshift; + blitDst.w = g.width; + blitDst.y = iY+g.fp->vshift; + blitDst.h = g.height; + + mySDL_BlitSurfaceSmartBlend( g.GetSurface(), &blitSrc, img, &blitDst ); + +// SDL_SaveBMP( img, "testingText.bmp" ); + + /* Advance the cursor. */ + iX += g.hadvance; + } + + /* The amount of padding a line needs: */ + iY += Padding; + } + + return img; +} \ No newline at end of file diff --git a/stepmania/src/CompositedText.h b/stepmania/src/CompositedText.h new file mode 100644 index 0000000000..a317f51362 --- /dev/null +++ b/stepmania/src/CompositedText.h @@ -0,0 +1,22 @@ +#ifndef CompositedText_H +#define CompositedText_H +/* +----------------------------------------------------------------------------- + Class: CompositedText + + Desc: A little graphic to the left of the song's text banner in the MusicWheel. + + Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. + Chris Danford +----------------------------------------------------------------------------- +*/ + +#include "Sprite.h" + +struct SDL_Surface; + + +SDL_Surface* CreateCompositedText( CString sFontFile, CString sText ); + + +#endif diff --git a/stepmania/src/CourseContentsList.h b/stepmania/src/CourseContentsList.h index 646fe09d7b..bf5d06429a 100644 --- a/stepmania/src/CourseContentsList.h +++ b/stepmania/src/CourseContentsList.h @@ -13,7 +13,6 @@ #include "DifficultyMeter.h" #include "BitmapText.h" -#include "TextBanner.h" #include "ActorFrame.h" #include "Sprite.h" #include "Quad.h" diff --git a/stepmania/src/Font.cpp b/stepmania/src/Font.cpp index f1ba854640..b863d50487 100644 --- a/stepmania/src/Font.cpp +++ b/stepmania/src/Font.cpp @@ -24,6 +24,8 @@ #include "GameManager.h" #include "FontCharmaps.h" #include "FontCharAliases.h" +#include "SDL_video.h" +#include "SDL_image.h" /* Last private-use Unicode character: */ const wchar_t Font::DEFAULT_GLYPH = 0xF8FF; @@ -31,6 +33,7 @@ const wchar_t Font::DEFAULT_GLYPH = 0xF8FF; FontPage::FontPage() { m_pTexture = NULL; + m_pSurface = NULL; } void FontPage::Load( FontPageSettings cfg ) @@ -42,7 +45,10 @@ void FontPage::Load( FontPageSettings cfg ) ID.bStretch = true; m_pTexture = TEXTUREMAN->LoadTexture( ID ); - ASSERT( m_pTexture != NULL ); + ASSERT( m_pTexture ); + + m_pSurface = IMG_Load( ID.filename ); + ASSERT( m_pSurface ); // load character widths vector FrameWidths; @@ -110,49 +116,64 @@ void FontPage::Load( FontPageSettings cfg ) void FontPage::SetTextureCoords(const vector &widths) { - for(int i = 0; i < m_pTexture->GetNumFrames(); ++i) + for(int y = 0; y < m_pTexture->GetFramesHigh(); ++y) { - glyph g; - - g.fp = this; - - /* Make a copy of each texture rect, reducing each to the actual dimensions - * of the character (most characters don't take a full block). */ - g.rect = *m_pTexture->GetTextureCoordRect(i);; - - /* Set the width and height to the width and line spacing, respectively. */ - g.width = float(widths[i]); - g.height = float(m_pTexture->GetSourceFrameHeight()); - - /* By default, advance one pixel more than the width. (This could be - * an option.) */ - g.hadvance = int(g.width + 1); - - /* Do the same thing with X. Do this by changing the actual rendered - * rect, instead of shifting it, so we don't render more than we need to. */ - g.hshift = 0; + for(int x = 0; x < m_pTexture->GetFramesWide(); ++x) { - int iPixelsToChopOff = m_pTexture->GetSourceFrameWidth() - widths[i]; - if((iPixelsToChopOff % 2) == 1) + int i = y*m_pTexture->GetFramesHigh() + x; + + glyph g; + + g.fp = this; + + /* Make a copy of each texture rect, reducing each to the actual dimensions + * of the character (most characters don't take a full block). */ + g.rect = *m_pTexture->GetTextureCoordRect(i); + + g.blitSrc = RectI( + m_pTexture->GetSourceFrameWidth()*x, + m_pTexture->GetSourceFrameHeight()*y, + m_pTexture->GetSourceFrameWidth()*(x+1), + m_pTexture->GetSourceFrameHeight()*(y+1) ); + + /* Set the width and height to the width and line spacing, respectively. */ + g.width = float(widths[i]); + g.height = float(m_pTexture->GetSourceFrameHeight()); + + /* By default, advance one pixel more than the width. (This could be + * an option.) */ + g.hadvance = int(g.width + 1); + + /* Do the same thing with X. Do this by changing the actual rendered + * rect, instead of shifting it, so we don't render more than we need to. */ + g.hshift = 0; { - /* We don't want to chop off an odd number of pixels, since that'll - * put our texture coordinates between texels and make things blurrier. - * Note that, since we set hadvance above, this merely expands what - * we render; it doesn't advance the cursor further. So, glyphs - * that have an odd width should err to being a pixel offcenter left, - * not right. */ - iPixelsToChopOff--; - g.width++; + int iPixelsToChopOff = m_pTexture->GetSourceFrameWidth() - widths[i]; + if((iPixelsToChopOff % 2) == 1) + { + /* We don't want to chop off an odd number of pixels, since that'll + * put our texture coordinates between texels and make things blurrier. + * Note that, since we set hadvance above, this merely expands what + * we render; it doesn't advance the cursor further. So, glyphs + * that have an odd width should err to being a pixel offcenter left, + * not right. */ + iPixelsToChopOff--; + g.width++; + } + g.blitSrc.left += iPixelsToChopOff/2; + g.blitSrc.right -= iPixelsToChopOff/2; + + float fTexCoordsToChopOff = float(iPixelsToChopOff) / m_pTexture->GetSourceWidth(); + + g.rect.left += fTexCoordsToChopOff/2; + g.rect.right -= fTexCoordsToChopOff/2; } - float fTexCoordsToChopOff = float(iPixelsToChopOff) / m_pTexture->GetSourceWidth(); - g.rect.left += fTexCoordsToChopOff/2; - g.rect.right -= fTexCoordsToChopOff/2; + g.Texture = m_pTexture; + g.Surface = m_pSurface; + + glyphs.push_back(g); } - - g.Texture = m_pTexture; - - glyphs.push_back(g); } } @@ -179,6 +200,8 @@ void FontPage::SetExtraPixels(int DrawExtraPixelsLeft, int DrawExtraPixelsRight) float ExtraRight = min( float(DrawExtraPixelsRight), (iFrameWidth-iCharWidth)/2.0f ); /* Move left and expand right. */ + glyphs[i].blitSrc.left -= ExtraLeft; + glyphs[i].blitSrc.right += ExtraRight; glyphs[i].rect.left -= ExtraLeft / m_pTexture->GetSourceWidth(); glyphs[i].rect.right += ExtraRight / m_pTexture->GetSourceWidth(); glyphs[i].hshift -= ExtraLeft; @@ -188,8 +211,10 @@ void FontPage::SetExtraPixels(int DrawExtraPixelsLeft, int DrawExtraPixelsRight) FontPage::~FontPage() { - if( m_pTexture != NULL ) + if( m_pTexture ) TEXTUREMAN->UnloadTexture( m_pTexture ); + if( m_pSurface ) + SDL_FreeSurface( m_pSurface ); } int Font::GetLineWidthInSourcePixels( const wstring &szLine ) const diff --git a/stepmania/src/Font.h b/stepmania/src/Font.h index 792aaae800..4ded792f75 100644 --- a/stepmania/src/Font.h +++ b/stepmania/src/Font.h @@ -16,11 +16,14 @@ #include "IniFile.h" class FontPage; +struct SDL_Surface; struct glyph { FontPage *fp; RageTexture *Texture; RageTexture *GetTexture() const { return const_cast(Texture); } + SDL_Surface *Surface; + SDL_Surface *GetSurface() const { return Surface; } /* Number of pixels to advance horizontally after drawing this character. */ int hadvance; @@ -33,6 +36,9 @@ struct glyph { /* Texture coordinate rect. */ RectF rect; + + /* rect in pixels */ + RectI blitSrc; }; struct FontPageSettings @@ -71,6 +77,7 @@ class FontPage { public: RageTexture* m_pTexture; + SDL_Surface* m_pSurface; CString m_sTexturePath; diff --git a/stepmania/src/JukeboxMenu.h b/stepmania/src/JukeboxMenu.h index 3268c388b4..8e93b8288e 100644 --- a/stepmania/src/JukeboxMenu.h +++ b/stepmania/src/JukeboxMenu.h @@ -13,10 +13,10 @@ #include "ActorFrame.h" #include "Banner.h" -#include "TextBanner.h" #include "GameConstantsAndTypes.h" #include "RandomSample.h" #include "Style.h" +#include "BitmapText.h" class JukeboxMenu: public ActorFrame diff --git a/stepmania/src/NoteDisplay.cpp b/stepmania/src/NoteDisplay.cpp index 122d4aaacf..7d7579f1e8 100644 --- a/stepmania/src/NoteDisplay.cpp +++ b/stepmania/src/NoteDisplay.cpp @@ -400,8 +400,7 @@ void NoteDisplay::DrawHold( const HoldNote& hn, const bool bActive, const float const float fYTail = bReverse ? fStartYPos : fEndYPos; // the center the tail const bool bWavy = GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_fEffects[PlayerOptions::EFFECT_DRUNK] > 0; - const int fYStep = bWavy ? 16 : 16;// causes crash w/ some NoteSkins : 128; // use small steps only if wavy - // If you don't include the 128 you can't compile this code!!!!!!! - Andy. + const int fYStep = 16; //bWavy ? 16 : 128; // use small steps only if wavy const float fColorScale = 1*fLife + (1-fLife)*cache->m_fHoldNGGrayPercent; diff --git a/stepmania/src/PrefsManager.cpp b/stepmania/src/PrefsManager.cpp index fbfc5bb234..756499bb89 100644 --- a/stepmania/src/PrefsManager.cpp +++ b/stepmania/src/PrefsManager.cpp @@ -84,7 +84,7 @@ PrefsManager::PrefsManager() m_iCoinsPerCredit = 1; m_bJointPremium = false; m_iBoostAppPriority = -1; - m_iPolygonRadar = -1; + m_bAntiAliasing = false; m_ShowSongOptions = YES; m_bDancePointsForOni = false; m_bTimestamping = false; @@ -112,7 +112,7 @@ PrefsManager::PrefsManager() m_bHiddenSongs = false; m_bVsync = true; - m_sVideoRenderers = ""; + m_sVideoRenderers = ""; // StepMania.cpp sets this on first run m_sSoundDrivers = DEFAULT_SOUND_DRIVER_LIST; m_fSoundVolume = DEFAULT_SOUND_VOLUME; /* This is experimental: let's see if preloading helps people's skipping. @@ -178,8 +178,6 @@ void PrefsManager::ReadGlobalPrefsFromDisk( bool bSwitchToLastPlayedGame ) ini.GetValueB( "Options", "DelayedScreenLoad", m_bDelayedScreenLoad ); ini.GetValueI( "Options", "MusicWheelUsesSections", (int&)m_MusicWheelUsesSections ); ini.GetValueI( "Options", "MusicWheelSwitchSpeed", m_iMusicWheelSwitchSpeed ); - ini.GetValue ( "Options", "VideoRenderers", m_sVideoRenderers ); - ini.GetValue ( "Options", "LastSeenVideoDriver", m_sLastSeenVideoDriver ); ini.GetValue ( "Options", "SoundDrivers", m_sSoundDrivers ); ini.GetValueB( "Options", "EasterEggs", m_bEasterEggs ); ini.GetValueB( "Options", "MarvelousTiming", m_bMarvelousTiming ); @@ -189,7 +187,6 @@ void PrefsManager::ReadGlobalPrefsFromDisk( bool bSwitchToLastPlayedGame ) ini.GetValueI( "Options", "CoinsPerCredit", m_iCoinsPerCredit ); ini.GetValueB( "Options", "JointPremium", m_bJointPremium ); ini.GetValueI( "Options", "BoostAppPriority", m_iBoostAppPriority ); - ini.GetValueI( "Options", "PolygonRadar", m_iPolygonRadar ); ini.GetValueB( "Options", "PickExtraStage", m_bPickExtraStage ); ini.GetValueF( "Options", "LongVerSeconds", m_fLongVerSongSeconds ); ini.GetValueF( "Options", "MarathonVerSeconds", m_fMarathonVerSongSeconds ); @@ -210,6 +207,9 @@ void PrefsManager::ReadGlobalPrefsFromDisk( bool bSwitchToLastPlayedGame ) ini.GetValueB( "Options", "UseUnlockSystem", m_bUseUnlockSystem ); ini.GetValueB( "Options", "FirstRun", m_bFirstRun ); ini.GetValueB( "Options", "AutoMapJoysticks", m_bAutoMapJoysticks ); + ini.GetValue ( "Options", "LastSeenVideoDriver", m_sLastSeenVideoDriver ); + ini.GetValue ( "Options", "VideoRenderers", m_sVideoRenderers ); + ini.GetValueB( "Options", "AntiAliasing", m_bAntiAliasing ); m_asAdditionalSongFolders.clear(); CString sAdditionalSongFolders; @@ -278,7 +278,6 @@ void PrefsManager::SaveGlobalPrefsToDisk() ini.SetValueI( "Options", "CoinsPerCredit", m_iCoinsPerCredit ); ini.SetValueB( "Options", "JointPremium", m_bJointPremium ); ini.SetValueI( "Options", "BoostAppPriority", m_iBoostAppPriority ); - ini.SetValueI( "Options", "PolygonRadar", m_iPolygonRadar ); ini.SetValueB( "Options", "PickExtraStage", m_bPickExtraStage ); ini.SetValueF( "Options", "LongVerSeconds", m_fLongVerSongSeconds ); ini.SetValueF( "Options", "MarathonVerSeconds", m_fMarathonVerSongSeconds ); @@ -298,7 +297,9 @@ void PrefsManager::SaveGlobalPrefsToDisk() ini.SetValueB( "Options", "UseUnlockSystem", m_bUseUnlockSystem ); ini.SetValueB( "Options", "FirstRun", m_bFirstRun ); ini.SetValueB( "Options", "AutoMapJoysticks", m_bAutoMapJoysticks ); - + ini.SetValue ( "Options", "VideoRenderers", m_sVideoRenderers ); + ini.SetValue ( "Options", "LastSeenVideoDriver", m_sLastSeenVideoDriver ); + ini.SetValueB( "Options", "AntiAliasing", m_bAntiAliasing ); /* Only write these if they aren't the default. This ensures that we can change * the default and have it take effect for everyone (except people who @@ -307,8 +308,6 @@ void PrefsManager::SaveGlobalPrefsToDisk() ini.SetValue ( "Options", "SoundDrivers", m_sSoundDrivers ); if(m_fSoundVolume != DEFAULT_SOUND_VOLUME) ini.SetValueF( "Options", "SoundVolume", m_fSoundVolume ); - if(m_sVideoRenderers != "") - ini.SetValue ( "Options", "Renderer", m_sVideoRenderers ); ini.SetValue( "Options", "AdditionalSongFolders", join(",", m_asAdditionalSongFolders) ); diff --git a/stepmania/src/PrefsManager.h b/stepmania/src/PrefsManager.h index 72ead05236..17c631abd1 100644 --- a/stepmania/src/PrefsManager.h +++ b/stepmania/src/PrefsManager.h @@ -85,14 +85,12 @@ public: /* 0 = no; 1 = yes; -1 = auto (do whatever is appropriate for the arch). */ int m_iBoostAppPriority; - /* 0 = no; 1 = yes; -1 = auto (turn on for known-bad drivers) */ - int m_iPolygonRadar; - CStringArray m_asAdditionalSongFolders; CString m_DWIPath; - CString m_sVideoRenderers; CString m_sLastSeenVideoDriver; + CString m_sVideoRenderers; + bool m_bAntiAliasing; CString m_sSoundDrivers; float m_fSoundVolume; bool m_bSoundPreloadAll; diff --git a/stepmania/src/RageBitmapTexture.cpp b/stepmania/src/RageBitmapTexture.cpp index 27c96cb773..fb512444af 100644 --- a/stepmania/src/RageBitmapTexture.cpp +++ b/stepmania/src/RageBitmapTexture.cpp @@ -25,6 +25,8 @@ #include "SDL_utils.h" #include "SDL_dither.h" +#include "CompositedText.h" + #include "RageTimer.h" static void GetResolutionFromFileName( CString sPath, int &Width, int &Height ) @@ -82,12 +84,21 @@ void RageBitmapTexture::Create() /* Create (and return) a surface ready to be loaded to OpenGL */ /* Load the image into an SDL surface. */ - SDL_Surface *img = IMG_Load(GetFilePath()); + SDL_Surface *img; + if( GetID().filename.Right(3).CompareNoCase("ini")==0 ) + { + img = CreateCompositedText( GetID().filename, GetID().text ); + } + else + { + img = IMG_Load( GetID().filename ); + } + /* XXX: Wait, we don't want to throw for all images; in particular, we * want to tolerate corrupt/unknown background images. */ if(img == NULL) - RageException::Throw( "RageBitmapTexture: Couldn't load %s: %s", GetFilePath().c_str(), SDL_GetError() ); + RageException::Throw( "RageBitmapTexture: Couldn't load %s: %s", GetID().filename.c_str(), SDL_GetError() ); if(actualID.bHotPinkColorKey) { @@ -111,7 +122,7 @@ void RageBitmapTexture::Create() } // look in the file name for a format hints - CString HintString = GetFilePath(); + CString HintString = GetID().filename; HintString.MakeLower(); if( HintString.Find("4alphaonly") != -1 ) actualID.iTransparencyOnly = 4; diff --git a/stepmania/src/RageDisplay.cpp b/stepmania/src/RageDisplay.cpp index e2dbb7c05f..c09a5a3f4b 100644 --- a/stepmania/src/RageDisplay.cpp +++ b/stepmania/src/RageDisplay.cpp @@ -48,6 +48,53 @@ CString PixelFormatToString( PixelFormat pixfmt ) return s[pixfmt]; }; +// Return true if device was re-created and we need to reload textures. +bool RageDisplay::SetVideoMode( VideoModeParams p ) +{ + /* Round to the nearest valid fullscreen resolution */ + if( !p.windowed ) + { + if( p.width <= 320 ) p.width = 320; + else if( p.width <= 400 ) p.width = 400; + else if( p.width <= 512 ) p.width = 512; + else if( p.width <= 640 ) p.width = 640; + else if( p.width <= 800 ) p.width = 800; + else if( p.width <= 1024 ) p.width = 1024; + else if( p.width <= 1280 ) p.width = 1280; + + switch( p.width ) + { + case 320: p.height = 240; break; + case 400: p.height = 300; break; + case 512: p.height = 384; break; + case 640: p.height = 480; break; + case 800: p.height = 600; break; + case 1024: p.height = 768; break; + case 1280: p.height = 960; break; + default: ASSERT(0); + } + } + + bool bNeedReloadTextures; + + if( this->TryVideoMode(p,bNeedReloadTextures) ) + return bNeedReloadTextures; + + // fall back + p.windowed = false; + if( this->TryVideoMode(p,bNeedReloadTextures) ) + return bNeedReloadTextures; + p.bpp = 16; + if( this->TryVideoMode(p,bNeedReloadTextures) ) + return bNeedReloadTextures; + p.width = 640; + p.height = 480; + if( this->TryVideoMode(p,bNeedReloadTextures) ) + return bNeedReloadTextures; + + RageException::Throw( "SetVideoMode failed. Tried to fall back to other modes, but nothing worked." ); +} + void RageDisplay::ProcessStatsOnFlip() { g_iFramesRenderedSinceLastCheck++; diff --git a/stepmania/src/RageDisplay.h b/stepmania/src/RageDisplay.h index db90720cd8..d3e61ecdab 100644 --- a/stepmania/src/RageDisplay.h +++ b/stepmania/src/RageDisplay.h @@ -59,24 +59,63 @@ class RageDisplay friend class RageTexture; public: + + struct VideoModeParams + { + // Initialize with a constructor so to guarantee all paramters + // are filled (in case new params are added). + VideoModeParams( + bool _windowed, + int _width, + int _height, + int _bpp, + int _rate, + bool _vsync, + bool _bAntiAliasing, + CString _sWindowTitle, + CString _sIconFile ) + { + windowed = _windowed; + width = _width; + height = _height; + bpp = _bpp; + rate = _rate; + vsync = _vsync; + bAntiAliasing = _bAntiAliasing; + sWindowTitle = _sWindowTitle; + sIconFile = _sIconFile; + } + VideoModeParams() {} + + bool windowed; + int width; + int height; + int bpp; + int rate; + bool vsync; + bool bAntiAliasing; + CString sWindowTitle; + CString sIconFile; + }; + virtual const PixelFormatDesc *GetPixelFormatDesc(PixelFormat pf) const = 0; -// RageDisplay( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ); - virtual ~RageDisplay() { }; + virtual void Update(float fDeltaTime) { } virtual bool IsSoftwareRenderer() = 0; - virtual bool SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ) = 0; + // Don't override this. Override TryVideoMode() instead. + // This will set the video mode to be as close as possible to params. + // Return true if device was re-created and we need to reload textures. + bool SetVideoMode( VideoModeParams params ); /* Call this when the resolution has been changed externally: */ virtual void ResolutionChanged() { } virtual void BeginFrame() = 0; virtual void EndFrame() = 0; - virtual bool IsWindowed() const = 0; - virtual int GetWidth() const = 0; - virtual int GetHeight() const = 0; - virtual int GetBPP() const = 0; + virtual VideoModeParams GetVideoModeParams() const = 0; + bool IsWindowed() const { return this->GetVideoModeParams().windowed; } virtual void SetBlendMode( BlendMode mode ) = 0; @@ -140,6 +179,11 @@ public: virtual void SaveScreenshot( CString sPath ) = 0; protected: + // Return true if mode change was successful. + // bNewDeviceOut is set true if a new device was created and textures + // need to be reloaded. + virtual bool TryVideoMode( VideoModeParams params, bool &bNewDeviceOut ) = 0; + virtual void SetViewport(int shift_left, int shift_down) = 0; void DrawPolyLine(const RageVertex &p1, const RageVertex &p2, float LineWidth ); diff --git a/stepmania/src/RageDisplay_D3D.cpp b/stepmania/src/RageDisplay_D3D.cpp index 792eaf5d82..71809550d1 100644 --- a/stepmania/src/RageDisplay_D3D.cpp +++ b/stepmania/src/RageDisplay_D3D.cpp @@ -56,8 +56,7 @@ D3DCAPS8 g_DeviceCaps; D3DDISPLAYMODE g_DesktopMode; D3DPRESENT_PARAMETERS g_d3dpp; int g_ModelMatrixCnt=0; -bool g_Windowed; -int g_CurrentHeight, g_CurrentWidth, g_CurrentBPP; +RageDisplay::VideoModeParams g_CurrentParams; /* Direct3D doesn't associate a palette with textures. * Instead, we load a palette into a slot. We need to keep track @@ -187,7 +186,7 @@ const PixelFormatDesc *RageDisplay_D3D::GetPixelFormatDesc(PixelFormat pf) const -RageDisplay_D3D::RageDisplay_D3D( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ) +RageDisplay_D3D::RageDisplay_D3D( VideoModeParams p ) { LOG->Trace( "RageDisplay_D3D::RageDisplay_D3D()" ); LOG->MapLog("renderer", "Current renderer: Direct3D"); @@ -247,8 +246,6 @@ RageDisplay_D3D::RageDisplay_D3D( bool windowed, int width, int height, int bpp, SDL_EventState(0xFF /*SDL_ALLEVENTS*/, SDL_IGNORE); SDL_EventState(SDL_VIDEORESIZE, SDL_ENABLE); - g_Windowed = false; - g_PaletteIndex.clear(); for( int i = 0; i < 256; ++i ) g_PaletteIndex.push_back(i); @@ -256,23 +253,16 @@ RageDisplay_D3D::RageDisplay_D3D( bool windowed, int width, int height, int bpp, // Save the original desktop format. g_pd3d->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &g_DesktopMode ); - // Create the SDL window int flags = SDL_RESIZABLE | SDL_SWSURFACE; - SDL_Surface *screen = SDL_SetVideoMode(width, height, bpp, flags); + SDL_Surface *screen = SDL_SetVideoMode(p.width, p.height, p.bpp, flags); if(!screen) { SDL_QuitSubSystem(SDL_INIT_VIDEO); // exit out of full screen. The ~RageDisplay will not be called! RageException::Throw("SDL_SetVideoMode failed: %s", SDL_GetError()); } - - if( SetVideoMode( windowed, width, height, bpp, rate, vsync, sWindowTitle, sIconFile ) ) - return; - if( SetVideoMode( false, width, height, bpp, rate, vsync, sWindowTitle, sIconFile ) ) - return; - if( SetVideoMode( false, width, height, 16, rate, vsync, sWindowTitle, sIconFile ) ) - return; + SetVideoMode( p ); } void RageDisplay_D3D::Update(float fDeltaTime) @@ -283,8 +273,8 @@ void RageDisplay_D3D::Update(float fDeltaTime) switch(event.type) { case SDL_VIDEORESIZE: - g_CurrentWidth = event.resize.w; - g_CurrentHeight = event.resize.h; + g_CurrentParams.width = event.resize.w; + g_CurrentParams.height = event.resize.h; /* Let DISPLAY know that our resolution has changed. */ ResolutionChanged(); @@ -382,41 +372,18 @@ HWND GetHwnd() /* Set the video mode. */ -bool RageDisplay_D3D::SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ) +bool RageDisplay_D3D::TryVideoMode( VideoModeParams p, bool &bNewDeviceOut ) { + g_CurrentParams = p; + HRESULT hr; - if( FindBackBufferType( windowed, bpp ) == -1 ) // no possible back buffer formats - return false; + if( FindBackBufferType( p.windowed, p.bpp ) == -1 ) // no possible back buffer formats + return false; // failed to set mode /* Set SDL window title and icon -before- creating the window */ - SDL_WM_SetCaption(sWindowTitle, ""); - mySDL_WM_SetIcon( sIconFile ); - - - /* Round to the nearest valid fullscreen resolution */ - if( !windowed ) - { - if( width <= 320 ) width = 320; - else if( width <= 400 ) width = 400; - else if( width <= 512 ) width = 512; - else if( width <= 640 ) width = 640; - else if( width <= 800 ) width = 800; - else if( width <= 1024 ) width = 1024; - else if( width <= 1280 ) width = 1280; - - switch( width ) - { - case 320: height = 240; break; - case 400: height = 300; break; - case 512: height = 384; break; - case 640: height = 480; break; - case 800: height = 600; break; - case 1024: height = 768; break; - case 1280: height = 960; break; - default: ASSERT(0); - } - } + SDL_WM_SetCaption( p.sWindowTitle, "" ); + mySDL_WM_SetIcon( p.sIconFile ); // HACK: On Windows 98, we can't call SDL_SetVideoMode while D3D is full screen. @@ -424,22 +391,17 @@ bool RageDisplay_D3D::SetVideoMode( bool windowed, int width, int height, int bp // Not in exclusive access mode". So, we'll Reset the D3D device, then resize the // SDL window only if we're not fullscreen. - g_Windowed = windowed; - g_CurrentWidth = width; - g_CurrentHeight = height; - g_CurrentBPP = bpp; - - SDL_ShowCursor( windowed ); + SDL_ShowCursor( p.windowed ); ZeroMemory( &g_d3dpp, sizeof(g_d3dpp) ); - g_d3dpp.BackBufferWidth = width; - g_d3dpp.BackBufferHeight = height; - g_d3dpp.BackBufferFormat = FindBackBufferType( windowed, bpp ); + g_d3dpp.BackBufferWidth = p.width; + g_d3dpp.BackBufferHeight = p.height; + g_d3dpp.BackBufferFormat = FindBackBufferType( p.windowed, p.bpp ); g_d3dpp.BackBufferCount = 1; g_d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; g_d3dpp.hDeviceWindow = NULL; - g_d3dpp.Windowed = windowed; + g_d3dpp.Windowed = p.windowed; g_d3dpp.EnableAutoDepthStencil = TRUE; g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16; g_d3dpp.Flags = 0; @@ -447,7 +409,7 @@ bool RageDisplay_D3D::SetVideoMode( bool windowed, int width, int height, int bp /* Windowed must always use D3DPRESENT_INTERVAL_DEFAULT. */ g_d3dpp.FullScreen_PresentationInterval = - (windowed || vsync) ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE; + (p.windowed || p.vsync) ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE; LOG->Trace( "Present Parameters: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d", g_d3dpp.BackBufferWidth, g_d3dpp.BackBufferHeight, g_d3dpp.BackBufferFormat, @@ -458,10 +420,9 @@ bool RageDisplay_D3D::SetVideoMode( bool windowed, int width, int height, int bp g_d3dpp.FullScreen_PresentationInterval ); - bool bCreateNewDevice = g_pd3dDevice == NULL; - - if( bCreateNewDevice ) // device is not yet created. We need to create it + if( g_pd3dDevice == NULL ) // device is not yet created. We need to create it { + bNewDeviceOut = true; hr = g_pd3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, @@ -482,6 +443,7 @@ bool RageDisplay_D3D::SetVideoMode( bool windowed, int width, int height, int bp } else { + bNewDeviceOut = false; hr = g_pd3dDevice->Reset( &g_d3dpp ); if( FAILED(hr) ) { @@ -490,7 +452,7 @@ bool RageDisplay_D3D::SetVideoMode( bool windowed, int width, int height, int bp } } - if( this->IsWindowed() ) + if( p.windowed ) { int flags = SDL_RESIZABLE | SDL_SWSURFACE; @@ -499,9 +461,9 @@ bool RageDisplay_D3D::SetVideoMode( bool windowed, int width, int height, int bp // if( !windowed ) // flags |= SDL_FULLSCREEN; - SDL_ShowCursor( g_Windowed ); + SDL_ShowCursor( p.windowed ); - SDL_Surface *screen = SDL_SetVideoMode(width, height, bpp, flags); + SDL_Surface *screen = SDL_SetVideoMode(p.width, p.height, p.bpp, flags); if(!screen) { SDL_QuitSubSystem(SDL_INIT_VIDEO); // exit out of full screen. The ~RageDisplay will not be called! @@ -516,7 +478,7 @@ bool RageDisplay_D3D::SetVideoMode( bool windowed, int width, int height, int bp /* Palettes were lost by Reset(), so mark them unloaded. */ g_TexResourceToPaletteIndex.clear(); - return bCreateNewDevice; + return true; // mode change successful } void RageDisplay_D3D::ResolutionChanged() @@ -533,10 +495,10 @@ void RageDisplay_D3D::SetViewport(int shift_left, int shift_down) { /* left and down are on a 0..SCREEN_WIDTH, 0..SCREEN_HEIGHT scale. * Scale them to the actual viewport range. */ - shift_left = int( shift_left * float(g_CurrentWidth) / SCREEN_WIDTH ); - shift_down = int( shift_down * float(g_CurrentHeight) / SCREEN_HEIGHT ); + shift_left = int( shift_left * float(g_CurrentParams.width) / SCREEN_WIDTH ); + shift_down = int( shift_down * float(g_CurrentParams.height) / SCREEN_HEIGHT ); - D3DVIEWPORT8 viewData = { shift_left, -shift_down, g_CurrentWidth, g_CurrentHeight, 0.f, 1.f }; + D3DVIEWPORT8 viewData = { shift_left, -shift_down, g_CurrentParams.width, g_CurrentParams.height, 0.f, 1.f }; g_pd3dDevice->SetViewport( &viewData ); } @@ -548,7 +510,7 @@ int RageDisplay_D3D::GetMaxTextureSize() const void RageDisplay_D3D::BeginFrame() { if( g_pd3dDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET ) - SetVideoMode( g_Windowed, g_CurrentWidth, g_CurrentHeight, g_CurrentBPP, 0, 0, "", "" ); // FIXME: preserve prefs + SetVideoMode( g_CurrentParams ); g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0x00000000 ); @@ -585,11 +547,7 @@ void RageDisplay_D3D::SaveScreenshot( CString sPath ) #endif } - -bool RageDisplay_D3D::IsWindowed() const { return g_Windowed; } -int RageDisplay_D3D::GetWidth() const { return g_CurrentWidth; } -int RageDisplay_D3D::GetHeight() const { return g_CurrentHeight; } -int RageDisplay_D3D::GetBPP() const { return g_CurrentBPP; } +RageDisplay::VideoModeParams RageDisplay_D3D::GetVideoModeParams() const { return g_CurrentParams; } #define SEND_CURRENT_MATRICES \ g_pd3dDevice->SetTransform( D3DTS_PROJECTION, (D3DMATRIX*)GetProjection() ); \ diff --git a/stepmania/src/RageDisplay_D3D.h b/stepmania/src/RageDisplay_D3D.h index d461a558a4..352233771f 100644 --- a/stepmania/src/RageDisplay_D3D.h +++ b/stepmania/src/RageDisplay_D3D.h @@ -7,21 +7,17 @@ class RageException_D3DNoAcceleration: public exception { }; class RageDisplay_D3D: public RageDisplay { public: - RageDisplay_D3D( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ); + RageDisplay_D3D( VideoModeParams params ); ~RageDisplay_D3D(); void Update(float fDeltaTime); bool IsSoftwareRenderer(); - bool SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ); void ResolutionChanged(); const PixelFormatDesc *GetPixelFormatDesc(PixelFormat pf) const; void BeginFrame(); void EndFrame(); - bool IsWindowed() const; - int GetWidth() const; - int GetHeight() const; - int GetBPP() const; + VideoModeParams GetVideoModeParams() const; void SetBlendMode( BlendMode mode ); bool SupportsTextureFormat( PixelFormat pixfmt ); unsigned CreateTexture( PixelFormat pixfmt, SDL_Surface*& img ); @@ -68,6 +64,7 @@ public: void SaveScreenshot( CString sPath ); protected: + bool TryVideoMode( VideoModeParams params, bool &bNewDeviceOut ); void SetViewport(int shift_left, int shift_down); RageMatrix GetOrthoMatrix( float l, float r, float b, float t, float zn, float zf ); diff --git a/stepmania/src/RageDisplay_OGL.cpp b/stepmania/src/RageDisplay_OGL.cpp index d74ef6f1ee..2695aee487 100644 --- a/stepmania/src/RageDisplay_OGL.cpp +++ b/stepmania/src/RageDisplay_OGL.cpp @@ -72,7 +72,6 @@ namespace GLExt { PWSWAPINTERVALEXTPROC GLExt::wglSwapIntervalEXT = NULL; PFNGLCOLORTABLEPROC GLExt::glColorTableEXT = NULL; PFNGLCOLORTABLEPARAMETERIVPROC GLExt::glGetColorTableParameterivEXT = NULL; -bool g_bAALinesBroken = false; bool g_bEXT_texture_env_combine = true; /* OpenGL system information that generally doesn't change at runtime. */ @@ -193,14 +192,14 @@ void GetGLExtensions(set &ext) ext.insert(lst[i]); } -RageDisplay_OGL::RageDisplay_OGL( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ) +RageDisplay_OGL::RageDisplay_OGL( VideoModeParams p ) { LOG->Trace( "RageDisplay_OGL::RageDisplay_OGL()" ); LOG->MapLog("renderer", "Current renderer: OpenGL"); wind = MakeLowLevelWindow(); - SetVideoMode( windowed, width, height, bpp, rate, vsync, sWindowTitle, sIconFile ); + SetVideoMode( p ); // Log driver details LOG->Info("OGL Vendor: %s", glGetString(GL_VENDOR)); @@ -306,22 +305,11 @@ void SetupExtensions() GLExt::wglSwapIntervalEXT = (PWSWAPINTERVALEXTPROC) wind->GetProcAddress("wglSwapIntervalEXT"); GLExt::glColorTableEXT = (PFNGLCOLORTABLEPROC) wind->GetProcAddress("glColorTableEXT"); GLExt::glGetColorTableParameterivEXT = (PFNGLCOLORTABLEPARAMETERIVPROC) wind->GetProcAddress("glGetColorTableParameterivEXT"); - g_bAALinesBroken = false; g_bEXT_texture_env_combine = HasExtension("GL_EXT_texture_env_combine"); CheckPalettedTextures(); // Checks for known bad drivers CString sRenderer = (const char*)glGetString(GL_RENDERER); - - if( sRenderer.Left(12) == "3Dfx/Voodoo3" ) - { - LOG->Info("Anti-aliased lines are known to cause problems with this driver."); - g_bAALinesBroken = true; -/* Shouldn't be needed anymore. - LOG->Info("Paletted textures are broken with this driver."); - GLExt::glColorTableEXT = NULL; - GLExt::glGetColorTableParameterivEXT = NULL; */ - } } void DumpOpenGLDebugInfo() @@ -390,21 +378,23 @@ void DumpOpenGLDebugInfo() void RageDisplay_OGL::ResolutionChanged() { - SetViewport(0,0); + SetViewport(0,0); /* Clear any junk that's in the framebuffer. */ BeginFrame(); EndFrame(); } -/* Set the video mode. In some cases, changing the video mode will reset - * the rendering context; returns true if we need to reload textures. */ -bool RageDisplay_OGL::SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ) +// Return true if mode change was successful. +// bNewDeviceOut is set true if a new device was created and textures +// need to be reloaded. +bool RageDisplay_OGL::TryVideoMode( VideoModeParams p, bool &bNewDeviceOut ) { // LOG->Trace( "RageDisplay_OGL::SetVideoMode( %d, %d, %d, %d, %d, %d )", windowed, width, height, bpp, rate, vsync ); - bool NewOpenGLContext = wind->SetVideoMode( windowed, width, height, bpp, rate, vsync, sWindowTitle, sIconFile ); + if( !wind->TryVideoMode( p, bNewDeviceOut ) ) + return false; // failed to set video mode - if(NewOpenGLContext) + if( bNewDeviceOut ) { /* We have a new OpenGL context, so we have to tell our textures that * their OpenGL texture number is invalid. */ @@ -422,21 +412,21 @@ bool RageDisplay_OGL::SetVideoMode( bool windowed, int width, int height, int bp /* Set vsync the Windows way, if we can. (What other extensions are there * to do this, for other archs?) */ if( GLExt::wglSwapIntervalEXT ) - GLExt::wglSwapIntervalEXT(vsync); + GLExt::wglSwapIntervalEXT(p.vsync); ResolutionChanged(); - return NewOpenGLContext; + return true; // successfully set mode } void RageDisplay_OGL::SetViewport(int shift_left, int shift_down) { /* left and down are on a 0..SCREEN_WIDTH, 0..SCREEN_HEIGHT scale. * Scale them to the actual viewport range. */ - shift_left = int( shift_left * float(wind->GetWidth()) / SCREEN_WIDTH ); - shift_down = int( shift_down * float(wind->GetHeight()) / SCREEN_HEIGHT ); + shift_left = int( shift_left * float(wind->GetVideoModeParams().width) / SCREEN_WIDTH ); + shift_down = int( shift_down * float(wind->GetVideoModeParams().height) / SCREEN_HEIGHT ); - glViewport(shift_left, -shift_down, wind->GetWidth(), wind->GetHeight()); + glViewport(shift_left, -shift_down, wind->GetVideoModeParams().width, wind->GetVideoModeParams().height); } int RageDisplay_OGL::GetMaxTextureSize() const @@ -473,23 +463,26 @@ void RageDisplay_OGL::SaveScreenshot( CString sPath ) { ASSERT( sPath.Right(3).CompareNoCase("bmp") == 0 ); // we can only save bitmaps + int width = wind->GetVideoModeParams().width; + int height = wind->GetVideoModeParams().height; + SDL_Surface *image = SDL_CreateRGBSurface( - SDL_SWSURFACE, wind->GetWidth(), wind->GetHeight(), + SDL_SWSURFACE, width, height, 24, 0x0000FF, 0x00FF00, 0xFF0000, 0x000000); SDL_Surface *temp = SDL_CreateRGBSurface( - SDL_SWSURFACE, wind->GetWidth(), wind->GetHeight(), + SDL_SWSURFACE, width, height, 24, 0x0000FF, 0x00FF00, 0xFF0000, 0x000000); - glReadPixels(0, 0, wind->GetWidth(), wind->GetHeight(), GL_RGB, + glReadPixels(0, 0, wind->GetVideoModeParams().width, wind->GetVideoModeParams().height, GL_RGB, GL_UNSIGNED_BYTE, image->pixels); // flip vertically int pitch = image->pitch; - for( int y=0; yGetHeight(); y++ ) + for( int y=0; yGetVideoModeParams().height; y++ ) memcpy( (char *)temp->pixels + pitch * y, - (char *)image->pixels + pitch * (wind->GetHeight()-1-y), - 3*wind->GetWidth() ); + (char *)image->pixels + pitch * (height-1-y), + 3*width ); SDL_SaveBMP( temp, sPath ); @@ -498,10 +491,7 @@ void RageDisplay_OGL::SaveScreenshot( CString sPath ) } -bool RageDisplay_OGL::IsWindowed() const { return wind->IsWindowed(); } -int RageDisplay_OGL::GetWidth() const { return wind->GetWidth(); } -int RageDisplay_OGL::GetHeight() const { return wind->GetHeight(); } -int RageDisplay_OGL::GetBPP() const { return wind->GetBPP(); } +RageDisplay::VideoModeParams RageDisplay_OGL::GetVideoModeParams() const { return wind->GetVideoModeParams(); } static void SetupVertices( const RageVertex v[], int iNumVerts ) { @@ -631,7 +621,7 @@ void RageDisplay_OGL::DrawLineStrip( const RageVertex v[], int iNumVerts, float { ASSERT( iNumVerts >= 2 ); - if( g_bAALinesBroken ) + if( !GetVideoModeParams().bAntiAliasing ) { RageDisplay::DrawLineStrip(v, iNumVerts, LineWidth ); return; @@ -650,8 +640,8 @@ void RageDisplay_OGL::DrawLineStrip( const RageVertex v[], int iNumVerts, float /* Our line width is wrt the regular internal SCREEN_WIDTHxSCREEN_HEIGHT screen, * but these width functions actually want raster sizes (that is, actual pixels). * Scale the line width and point size by the average ratio of the scale. */ - float WidthVal = float(wind->GetWidth()) / SCREEN_WIDTH; - float HeightVal = float(wind->GetHeight()) / SCREEN_HEIGHT; + float WidthVal = float(wind->GetVideoModeParams().width) / SCREEN_WIDTH; + float HeightVal = float(wind->GetVideoModeParams().height) / SCREEN_HEIGHT; LineWidth *= (WidthVal + HeightVal) / 2; /* Clamp the width to the hardware max for both lines and points (whichever diff --git a/stepmania/src/RageDisplay_OGL.h b/stepmania/src/RageDisplay_OGL.h index 9cbe4f1ed1..78f185e392 100644 --- a/stepmania/src/RageDisplay_OGL.h +++ b/stepmania/src/RageDisplay_OGL.h @@ -4,21 +4,17 @@ class RageDisplay_OGL: public RageDisplay { public: - RageDisplay_OGL( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ); + RageDisplay_OGL( VideoModeParams params ); ~RageDisplay_OGL(); void Update(float fDeltaTime); bool IsSoftwareRenderer(); - bool SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ); void ResolutionChanged(); const PixelFormatDesc *GetPixelFormatDesc(PixelFormat pf) const; void BeginFrame(); void EndFrame(); - bool IsWindowed() const; - int GetWidth() const; - int GetHeight() const; - int GetBPP() const; + VideoModeParams GetVideoModeParams() const; void SetBlendMode( BlendMode mode ); bool SupportsTextureFormat( PixelFormat pixfmt ); unsigned CreateTexture( PixelFormat pixfmt, SDL_Surface*& img ); @@ -65,6 +61,7 @@ public: void SaveScreenshot( CString sPath ); protected: + bool TryVideoMode( VideoModeParams params, bool &bNewDeviceOut ); void SetViewport(int shift_left, int shift_down); RageMatrix GetOrthoMatrix( float l, float r, float b, float t, float zn, float zf ); diff --git a/stepmania/src/RageMath.cpp b/stepmania/src/RageMath.cpp index be16bb5e29..156ec2cc0c 100644 --- a/stepmania/src/RageMath.cpp +++ b/stepmania/src/RageMath.cpp @@ -223,7 +223,7 @@ void RageMatrixCommand( CString sCommandString, RageMatrix &mat ) CString sError = ssprintf( "Unrecognized matrix command name '%s' in command string '%s'.", sName.c_str(), sCommandString.c_str() ); LOG->Warn( sError ); #if defined(WIN32) && !defined(_XBOX) // XXX arch? - if( DISPLAY->IsWindowed() ) + if( DISPLAY->GetVideoModeParams().windowed ) MessageBox(NULL, sError, "MatrixCommand", MB_OK); #endif continue; @@ -235,7 +235,7 @@ void RageMatrixCommand( CString sCommandString, RageMatrix &mat ) CString sError = ssprintf( "Wrong number of parameters in command '%s'. Expected %d but there are %d.", join(",",asTokens).c_str(), iMaxIndexAccessed+1, (int)asTokens.size() ); LOG->Warn( sError ); #if defined(WIN32) // XXX arch? - if( DISPLAY->IsWindowed() ) + if( DISPLAY->GetVideoModeParams().windowed ) MessageBox(NULL, sError, "MatrixCommand", MB_OK); #endif continue; diff --git a/stepmania/src/RageTexture.cpp b/stepmania/src/RageTexture.cpp index e18849e61d..04ec30874d 100644 --- a/stepmania/src/RageTexture.cpp +++ b/stepmania/src/RageTexture.cpp @@ -49,6 +49,7 @@ bool RageTextureID::operator<(const RageTextureID &rhs) const { #define COMP(a) if(arhs.a) return false; COMP(filename); + COMP(text); COMP(iMaxSize); COMP(iMipMaps); COMP(iAlphaBits); @@ -63,16 +64,18 @@ bool RageTextureID::operator<(const RageTextureID &rhs) const bool RageTextureID::operator==(const RageTextureID &rhs) const { +#define EQUAL(a) (a==rhs.a) return - filename == rhs.filename && - iMaxSize == rhs.iMaxSize && - iMipMaps == rhs.iMipMaps && - iAlphaBits == rhs.iAlphaBits && - iColorDepth == rhs.iColorDepth && - iTransparencyOnly == rhs.iTransparencyOnly && - bDither == rhs.bDither && - bStretch == rhs.bStretch && - bHotPinkColorKey == rhs.bHotPinkColorKey; + EQUAL(filename) && + EQUAL(text) && + EQUAL(iMaxSize) && + EQUAL(iMipMaps) && + EQUAL(iAlphaBits) && + EQUAL(iColorDepth) && + EQUAL(iTransparencyOnly) && + EQUAL(bDither) && + EQUAL(bStretch) && + EQUAL(bHotPinkColorKey); } @@ -114,7 +117,7 @@ RageTexture::~RageTexture() void RageTexture::CreateFrameRects() { - GetFrameDimensionsFromFileName( GetFilePath(), &m_iFramesWide, &m_iFramesHigh ); + GetFrameDimensionsFromFileName( GetID().filename, &m_iFramesWide, &m_iFramesHigh ); /////////////////////////////////// // Fill in the m_FrameRects with the bounds of each frame in the animation. diff --git a/stepmania/src/RageTexture.h b/stepmania/src/RageTexture.h index f9f9185e68..1ec4519434 100644 --- a/stepmania/src/RageTexture.h +++ b/stepmania/src/RageTexture.h @@ -21,7 +21,8 @@ * of these. */ struct RageTextureID { - CString filename; + CString filename; // font file name if !text.empty() + CString text; int iMaxSize; int iMipMaps; int iAlphaBits; @@ -82,7 +83,6 @@ public: const RectF *GetTextureCoordRect( int frameNo ) const; int GetNumFrames() const { return m_iFramesWide*m_iFramesHigh; } - const CString &GetFilePath() const { return GetID().filename; } int m_iRefCount; bool m_bCacheThis; diff --git a/stepmania/src/SDL_utils.cpp b/stepmania/src/SDL_utils.cpp index e4c6eb2a6b..f326e20514 100644 --- a/stepmania/src/SDL_utils.cpp +++ b/stepmania/src/SDL_utils.cpp @@ -602,6 +602,69 @@ void mySDL_WM_SetIcon( CString sIconFile ) SDL_FreeSurface(srf); } + +void mySDL_BlitSurfaceSmartBlend( + SDL_Surface* src, SDL_Rect *srcrect, + SDL_Surface* dst, SDL_Rect *dstrect ) +{ + /* Can't blit to paletted surfaces. */ + ASSERT(dst->format->BytesPerPixel > 1); + + /* Rects must be same dimensions. */ + ASSERT( srcrect->w==dstrect->w && srcrect->h==dstrect->h ); + + /* TODO: Add clipping. + * For now, just ASSERT if out of bounds. */ + ASSERT( + srcrect->x >= 0 && + srcrect->x+srcrect->w <= src->w && + srcrect->y >= 0 && + srcrect->y+srcrect->h <= src->h ); + ASSERT( + dstrect->x >= 0 && + dstrect->x+dstrect->w <= dst->w && + dstrect->y >= 0 && + dstrect->y+dstrect->h <= dst->h ); + + /* For each row: */ + for(int row = 0; row < srcrect->h; ++row) + { + const Uint8 *srcp = (const Uint8 *)src->pixels; + srcp += (srcrect->y+row) * src->pitch; + srcp += srcrect->x * src->format->BytesPerPixel; + Uint8 *dstp = (Uint8 *)dst->pixels; + dstp += (dstrect->y+row) * dst->pitch; + dstp += dstrect->x * dst->format->BytesPerPixel; + + /* For each pixel in row: */ + for(int col = 0; col < srcrect->w; ++col) + { + Uint8 srcColors[4]; + mySDL_GetRGBAV(srcp, src, srcColors); + + Uint8 dstColors[4]; + mySDL_GetRGBAV(dstp, dst, dstColors); + + float fColorWeightSrc = srcColors[3] / (float)(srcColors[3]+dstColors[3]); + float fColorWeightDst = dstColors[3] / (float)(srcColors[3]+dstColors[3]); + + Uint32 temp[4]; + temp[0] = srcColors[0] * fColorWeightSrc + dstColors[0] * fColorWeightDst; + temp[1] = srcColors[1] * fColorWeightSrc + dstColors[1] * fColorWeightDst; + temp[2] = srcColors[2] * fColorWeightSrc + dstColors[2] * fColorWeightDst; + temp[3] = srcColors[3] + (dstColors[3] * (255-srcColors[3]))/255; + + Uint8 blendedColors[4] = { temp[0], temp[1], temp[2], temp[3] }; + mySDL_SetRGBAV(dstp, dst, blendedColors); + + /* Next column */ + srcp += src->format->BytesPerPixel; + dstp += dst->format->BytesPerPixel; + } + } +} + + struct SurfaceHeader { int width, height, pitch; diff --git a/stepmania/src/SDL_utils.h b/stepmania/src/SDL_utils.h index f3b3fc8797..5727523673 100644 --- a/stepmania/src/SDL_utils.h +++ b/stepmania/src/SDL_utils.h @@ -56,6 +56,12 @@ int FindSurfaceTraits(const SDL_Surface *img); void mySDL_WM_SetIcon( CString sIconFile ); + +void mySDL_BlitSurfaceSmartBlend( + SDL_Surface* src, SDL_Rect *srcrect, + SDL_Surface* dst, SDL_Rect *dstrect ); + + bool mySDL_SaveSurface( SDL_Surface *img, CString file ); SDL_Surface *mySDL_LoadSurface( CString file ); diff --git a/stepmania/src/ScreenSandbox.cpp b/stepmania/src/ScreenSandbox.cpp index bdc88088df..e55bf5cda6 100644 --- a/stepmania/src/ScreenSandbox.cpp +++ b/stepmania/src/ScreenSandbox.cpp @@ -28,7 +28,7 @@ ScreenSandbox::ScreenSandbox() : Screen("ScreenSandbox") m_quad1.SetDiffuse( RageColor(0,0,1,1) ); m_quad1.SetZ( 0 ); m_quad1.SetUseZBuffer( true ); - this->AddChild( &m_quad1 ); +// this->AddChild( &m_quad1 ); m_quad2.StretchTo( RectI(SCREEN_LEFT, SCREEN_TOP, SCREEN_RIGHT, SCREEN_BOTTOM) ); m_quad2.SetDiffuse( RageColor(0,1,0,1) ); @@ -48,6 +48,13 @@ ScreenSandbox::ScreenSandbox() : Screen("ScreenSandbox") // this->AddChild(&m_model); // m_model.SetEffectSpin( RageVector3(0,90,90) ); + RageTextureID ID; + ID.filename = THEME->GetPathToF("MusicWheelItem roulette"); + ID.text = "testing,\ntesting,\n1\n2\n3\n\n\n"; + m_text.Load( ID ); + m_text.SetXY( CENTER_X, CENTER_Y ); + this->AddChild( &m_text ); + this->AddChild( &m_In ); this->AddChild( &m_Out ); diff --git a/stepmania/src/ScreenSandbox.h b/stepmania/src/ScreenSandbox.h index 83ea76dc15..fa227882be 100644 --- a/stepmania/src/ScreenSandbox.h +++ b/stepmania/src/ScreenSandbox.h @@ -34,6 +34,7 @@ public: Quad m_quad2; Transition m_In; Transition m_Out; + Sprite m_text; }; diff --git a/stepmania/src/StepMania.cpp b/stepmania/src/StepMania.cpp index e891e0c308..f92f58096b 100644 --- a/stepmania/src/StepMania.cpp +++ b/stepmania/src/StepMania.cpp @@ -88,14 +88,16 @@ void ApplyGraphicOptions() bool bNeedReload = false; bNeedReload |= DISPLAY->SetVideoMode( - PREFSMAN->m_bWindowed, - PREFSMAN->m_iDisplayWidth, - PREFSMAN->m_iDisplayHeight, - PREFSMAN->m_iDisplayColorDepth, - PREFSMAN->m_iRefreshRate, - PREFSMAN->m_bVsync, - THEME->GetMetric("Common","WindowTitle"), - THEME->GetPathToG("Common window icon") ); + RageDisplay::VideoModeParams( + PREFSMAN->m_bWindowed, + PREFSMAN->m_iDisplayWidth, + PREFSMAN->m_iDisplayHeight, + PREFSMAN->m_iDisplayColorDepth, + PREFSMAN->m_iRefreshRate, + PREFSMAN->m_bVsync, + PREFSMAN->m_bAntiAliasing, + THEME->GetMetric("Common","WindowTitle"), + THEME->GetPathToG("Common window icon") ) ); bNeedReload |= TEXTUREMAN->SetPrefs( PREFSMAN->m_iTextureColorDepth, PREFSMAN->m_bDelayedTextureDelete, @@ -104,14 +106,23 @@ void ApplyGraphicOptions() if( bNeedReload ) TEXTUREMAN->ReloadAll(); - SCREENMAN->SystemMessage( ssprintf("%s %dx%d %d color %d texture %dHz %s", + // find out what we actually got + PREFSMAN->m_bWindowed = DISPLAY->GetVideoModeParams().windowed; + PREFSMAN->m_iDisplayWidth = DISPLAY->GetVideoModeParams().width; + PREFSMAN->m_iDisplayHeight = DISPLAY->GetVideoModeParams().height; + PREFSMAN->m_iDisplayColorDepth = DISPLAY->GetVideoModeParams().bpp; + PREFSMAN->m_iRefreshRate = DISPLAY->GetVideoModeParams().rate; + PREFSMAN->m_bVsync = DISPLAY->GetVideoModeParams().vsync; + + SCREENMAN->SystemMessage( ssprintf("%s %dx%d %d color %d texture %dHz %s %s", PREFSMAN->m_bWindowed ? "Windowed" : "Fullscreen", PREFSMAN->m_iDisplayWidth, PREFSMAN->m_iDisplayHeight, PREFSMAN->m_iDisplayColorDepth, PREFSMAN->m_iTextureColorDepth, PREFSMAN->m_iRefreshRate, - PREFSMAN->m_bVsync ? "Vsync" : "NoSync" ) ); + PREFSMAN->m_bVsync ? "Vsync" : "NoVsync", + PREFSMAN->m_bAntiAliasing? "AA" : "NoAA" ) ); } void ExitGame() @@ -215,43 +226,6 @@ static void BoostAppPri() #include "RageDisplay_OGL.h" #endif -/* XXX: Passing all of the SetVideoMode arguments to the ctor is cumbersome. */ -#if !defined(_XBOX) -static RageDisplay *CreateDisplay_OGL() -{ - return new RageDisplay_OGL( - PREFSMAN->m_bWindowed, - PREFSMAN->m_iDisplayWidth, - PREFSMAN->m_iDisplayHeight, - PREFSMAN->m_iDisplayColorDepth, - PREFSMAN->m_iRefreshRate, - PREFSMAN->m_bVsync, - THEME->GetMetric("Common","WindowTitle"), - THEME->GetPathToG("Common window icon") ); -} -#endif - -#if defined(WIN32) -static RageDisplay *CreateDisplay_D3D() -{ - return new RageDisplay_D3D( - PREFSMAN->m_bWindowed, - PREFSMAN->m_iDisplayWidth, - PREFSMAN->m_iDisplayHeight, - PREFSMAN->m_iDisplayColorDepth, - PREFSMAN->m_iRefreshRate, - PREFSMAN->m_bVsync, - THEME->GetMetric("Common","WindowTitle"), - THEME->GetPathToG("Common window icon") ); -} -#endif - -#if defined(_XBOX) -RageDisplay *CreateDisplay() { return CreateDisplay_D3D(); } -#elif !defined(WIN32) -RageDisplay *CreateDisplay() { return CreateDisplay_OGL(); } -#else - #include "archutils/Win32/VideoDriverInfo.h" #include "Regex.h" @@ -314,6 +288,7 @@ RageDisplay *CreateDisplay() ini.GetValueI( sKey, "Height", PREFSMAN->m_iDisplayHeight ); ini.GetValueI( sKey, "DisplayColor", PREFSMAN->m_iDisplayColorDepth ); ini.GetValueI( sKey, "TextureColor", PREFSMAN->m_iTextureColorDepth ); + ini.GetValueB( sKey, "AntiAliasing", PREFSMAN->m_bAntiAliasing ); // Update last seen video card PREFSMAN->m_sLastSeenVideoDriver = GetPrimaryVideoDriverName(); @@ -322,6 +297,18 @@ RageDisplay *CreateDisplay() } } + + RageDisplay::VideoModeParams params( + PREFSMAN->m_bWindowed, + PREFSMAN->m_iDisplayWidth, + PREFSMAN->m_iDisplayHeight, + PREFSMAN->m_iDisplayColorDepth, + PREFSMAN->m_iRefreshRate, + PREFSMAN->m_bVsync, + PREFSMAN->m_bAntiAliasing, + THEME->GetMetric("Common","WindowTitle"), + THEME->GetPathToG("Common window icon") ); + CString error = "There was an error while initializing your video card.\n\n" " PLEASE DO NOT FILE THIS ERROR AS A BUG!\n\n" "Video Driver: "+sVideoDriver+"\n\n"; @@ -334,42 +321,48 @@ RageDisplay *CreateDisplay() if( sRenderer.CompareNoCase("opengl")==0 ) { +#if !defined(_XBOX) /* Try to create an OpenGL renderer. This should always succeed. (Actually, * SDL may throw, but that only happens with broken driver installations, and * we probably don't want to fall back on D3D in that case anyway.) */ error += "Initializing OpenGL...\n"; - RageDisplay *ret = CreateDisplay_OGL(); + RageDisplay *ret = new RageDisplay_OGL( params ); if( PREFSMAN->m_bAllowUnacceleratedRenderer || !ret->IsSoftwareRenderer() ) return ret; else { error += "Your system is reporting that OpenGL hardware acceleration is not available. " - "Please obtain an updated driver from your video card manufacturer."; + "Please obtain an updated driver from your video card manufacturer.\n\n"; delete ret; } +#endif } else if( sRenderer.CompareNoCase("d3d")==0 ) { +#if defined(WIN32) error += "Initializing Direct3D...\n"; try { - return CreateDisplay_D3D(); + return new RageDisplay_D3D( params ); } catch(RageException_D3DNotInstalled e) { - error += "DirectX 8.1 or greater is not installed. You can download it from:\n"+D3DURL; + error += "DirectX 8.1 or greater is not installed. You can download it from:\n"+D3DURL+"\n\n"; } catch(RageException_D3DNoAcceleration e) { error += "Your system is reporting that Direct3D hardware acceleration is not available. " - "Please obtain an updated driver from your video card manufacturer."; + "Please obtain an updated driver from your video card manufacturer.\n\n"; }; +#endif } else RageException::Throw("Unknown video renderer value: %s", sRenderer.c_str() ); } + if( asRenderers.empty() ) + error += "No video renderers attempted.\n\n"; + RageException::Throw( error ); } -#endif static void RestoreAppPri() { diff --git a/stepmania/src/StepMania.dsp b/stepmania/src/StepMania.dsp index fd9b54f0e9..44f8cf99a8 100644 --- a/stepmania/src/StepMania.dsp +++ b/stepmania/src/StepMania.dsp @@ -61,10 +61,10 @@ LINK32=link.exe # SUBTRACT LINK32 /verbose /profile /pdb:none /incremental:no /nodefaultlib # Begin Special Build Tool IntDir=.\../Debug6 -TargetDir=\temp\stepmania +TargetDir=\stepmania\stepmania TargetName=StepMania-debug SOURCE="$(InputPath)" -PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ +PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi ia32.vdi # End Special Build Tool @@ -100,7 +100,7 @@ XBCP=xbecopy.exe # ADD BASE XBCP /NOLOGO # ADD XBCP /NOLOGO # Begin Special Build Tool -PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ +PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi ia32.vdi # End Special Build Tool @@ -137,10 +137,10 @@ LINK32=link.exe # SUBTRACT LINK32 /verbose /pdb:none # Begin Special Build Tool IntDir=.\../Release6 -TargetDir=\temp\stepmania +TargetDir=\stepmania\stepmania TargetName=StepMania SOURCE="$(InputPath)" -PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ +PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi ia32.vdi # End Special Build Tool @@ -1941,6 +1941,23 @@ SOURCE=.\BitmapText.h # End Source File # Begin Source File +SOURCE=.\CompositedText.cpp + +!IF "$(CFG)" == "StepMania - Win32 Debug" + +!ELSEIF "$(CFG)" == "StepMania - Xbox Debug" + +!ELSEIF "$(CFG)" == "StepMania - Win32 Release" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\CompositedText.h +# End Source File +# Begin Source File + SOURCE=.\mathlib.c !IF "$(CFG)" == "StepMania - Win32 Debug" diff --git a/stepmania/src/StepMania.vcproj b/stepmania/src/StepMania.vcproj index 59e31f4ac9..e15691cfb4 100644 --- a/stepmania/src/StepMania.vcproj +++ b/stepmania/src/StepMania.vcproj @@ -1661,6 +1661,12 @@ cl /Zl /nologo /c verstub.cpp /Fo"$(IntDir)"\ + + + + diff --git a/stepmania/src/TextBanner.cpp b/stepmania/src/TextBanner.cpp index 33783f5419..e849cb9d31 100644 --- a/stepmania/src/TextBanner.cpp +++ b/stepmania/src/TextBanner.cpp @@ -104,6 +104,14 @@ void TextBanner::LoadFromString( m_textSubTitle.SetZoom( fSubTitleZoom ); m_textArtist.SetZoom( fArtistZoom ); +// RageTextureID ID; +// ID.filename = THEME->GetPathToF("TextBanner"); +// ID.text = sDisplayTitle; +// m_textTitle.Load( ID ); +// ID.text = sDisplaySubTitle; +// m_textSubTitle.Load( ID ); +// ID.text = sDisplayArtist; +// m_textArtist.Load( ID ); m_textTitle.SetTextMaxWidth( g_fWidth, sDisplayTitle, sTranslitTitle ); m_textSubTitle.SetTextMaxWidth( g_fWidth, sDisplaySubTitle, sTranslitSubTitle ); m_textArtist.SetTextMaxWidth( g_fWidth, sDisplayArtist, sTranslitArtist ); diff --git a/stepmania/src/TextBanner.h b/stepmania/src/TextBanner.h index 385805c483..b9c7da57ab 100644 --- a/stepmania/src/TextBanner.h +++ b/stepmania/src/TextBanner.h @@ -28,6 +28,7 @@ public: private: BitmapText m_textTitle, m_textSubTitle, m_textArtist; + //Sprite m_textTitle, m_textSubTitle, m_textArtist; }; #endif diff --git a/stepmania/src/arch/LowLevelWindow/LowLevelWindow.h b/stepmania/src/arch/LowLevelWindow/LowLevelWindow.h index e594cea3e4..7ac164fbfd 100644 --- a/stepmania/src/arch/LowLevelWindow/LowLevelWindow.h +++ b/stepmania/src/arch/LowLevelWindow/LowLevelWindow.h @@ -4,6 +4,9 @@ /* This handles low-level operations that OGL 1.x doesn't give us. Normally, * we use SDL. Note that not all SDL operations go here; however, nothing * outside of this can assume that SDL has VIDEO initialized. */ + +#include "RageDisplay.h" // for RageDisplay::VideoModeParams + class LowLevelWindow { public: @@ -11,17 +14,15 @@ public: virtual void *GetProcAddress(CString s) = 0; - /* Set the video mode as close to the requested settings as possible. They're - * hints only; it's better to get the wrong mode than to bail out. */ - virtual bool SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ) = 0; + // Return true if mode change was successful. + // bNewDeviceOut is set true if a new device was created and textures + // need to be reloaded. + virtual bool TryVideoMode( RageDisplay::VideoModeParams p, bool &bNewDeviceOut ) = 0; virtual void SwapBuffers() = 0; virtual void Update(float fDeltaTime) { } - virtual bool IsWindowed() const = 0; - virtual int GetWidth() const = 0; - virtual int GetHeight() const = 0; - virtual int GetBPP() const = 0; + virtual RageDisplay::VideoModeParams GetVideoModeParams() const = 0; }; #endif diff --git a/stepmania/src/arch/LowLevelWindow/LowLevelWindow_SDL.cpp b/stepmania/src/arch/LowLevelWindow/LowLevelWindow_SDL.cpp index f2affd01be..32139722b7 100644 --- a/stepmania/src/arch/LowLevelWindow/LowLevelWindow_SDL.cpp +++ b/stepmania/src/arch/LowLevelWindow/LowLevelWindow_SDL.cpp @@ -18,8 +18,6 @@ LowLevelWindow_SDL::LowLevelWindow_SDL() SDL_EventState(SDL_VIDEORESIZE, SDL_ENABLE); SDL_EventState(SDL_ACTIVEEVENT, SDL_ENABLE); - - Windowed = false; } LowLevelWindow_SDL::~LowLevelWindow_SDL() @@ -34,8 +32,10 @@ void *LowLevelWindow_SDL::GetProcAddress(CString s) return SDL_GL_GetProcAddress(s); } -bool LowLevelWindow_SDL::SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ) +bool LowLevelWindow_SDL::TryVideoMode( RageDisplay::VideoModeParams p, bool &bNewDeviceOut ) { + CurrentParams = p; + /* We need to preserve the event mask and all events, since they're lost by * SDL_QuitSubSystem(SDL_INIT_VIDEO). */ vector events; @@ -72,21 +72,18 @@ bool LowLevelWindow_SDL::SetVideoMode( bool windowed, int width, int height, int mySDL_PushEvents(events); /* Set SDL window title and icon -before- creating the window */ - SDL_WM_SetCaption(sWindowTitle, ""); - mySDL_WM_SetIcon( sIconFile ); + SDL_WM_SetCaption( p.sWindowTitle, ""); + mySDL_WM_SetIcon( p.sIconFile ); - Windowed = false; - int flags = SDL_RESIZABLE | SDL_OPENGL; // | SDL_DOUBLEBUF; // no need for DirectDraw to be double-buffered - if( !windowed ) + if( !p.windowed ) flags |= SDL_FULLSCREEN; - Windowed = windowed; - SDL_ShowCursor( Windowed ); + SDL_ShowCursor( p.windowed ); - ASSERT( bpp == 16 || bpp == 32 ); - switch( bpp ) + ASSERT( p.bpp == 16 || p.bpp == 32 ); + switch( p.bpp ) { case 16: SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); @@ -103,25 +100,29 @@ bool LowLevelWindow_SDL::SetVideoMode( bool windowed, int width, int height, int SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, true); #ifdef SDL_HAS_REFRESH_RATE - if(rate == REFRESH_DEFAULT) + if( p.rate == REFRESH_DEFAULT ) SDL_SM_SetRefreshRate(0); else - SDL_SM_SetRefreshRate(rate); + SDL_SM_SetRefreshRate(p.rate); #endif #if defined(WIN32) // mySDL_EventState(SDL_OPENGLRESET, SDL_ENABLE); #endif - SDL_Surface *screen = SDL_SetVideoMode(width, height, bpp, flags); + SDL_Surface *screen = SDL_SetVideoMode(p.width, p.height, p.bpp, flags); if(!screen) - RageException::Throw("SDL_SetVideoMode failed: %s", SDL_GetError()); + { + LOG->Trace("SDL_SetVideoMode failed: %s", SDL_GetError()); + return false; // failed to set mode + } - bool NewOpenGLContext = true; // always a new context because we're resetting SDL_Video + bNewDeviceOut = true; // always a new context because we're resetting SDL_Video /* XXX: This event only exists in the SDL tree, and is only needed in * Windows. Eventually, it'll probably get upstreamed, and once it's * in the real branch we can remove this #if. */ + /* Why did I comment this out? -Chris */ #if defined(WIN32) // SDL_Event e; // if(SDL_GetEvent(e, SDL_OPENGLRESETMASK)) @@ -151,11 +152,7 @@ bool LowLevelWindow_SDL::SetVideoMode( bool windowed, int width, int height, int colorbits, r, g, b, a, depth, stencil); } - CurrentWidth = screen->w; - CurrentHeight = screen->h; - CurrentBPP = bpp; - - return NewOpenGLContext; + return true; // we set the video mode successfully } void LowLevelWindow_SDL::SwapBuffers() @@ -171,26 +168,18 @@ void LowLevelWindow_SDL::Update(float fDeltaTime) switch(event.type) { case SDL_VIDEORESIZE: - CurrentWidth = event.resize.w; - CurrentHeight = event.resize.h; + CurrentParams.width = event.resize.w; + CurrentParams.height = event.resize.h; /* Let DISPLAY know that our resolution has changed. */ DISPLAY->ResolutionChanged(); break; case SDL_ACTIVEEVENT: if( event.active.gain && // app regaining focus - !DISPLAY->IsWindowed() ) // full screen + !DISPLAY->GetVideoModeParams().windowed ) // full screen { // need to reacquire an OGL context - DISPLAY->SetVideoMode( - DISPLAY->IsWindowed(), - DISPLAY->GetWidth(), - DISPLAY->GetHeight(), - DISPLAY->GetBPP(), - 0, - 0, - "", - "" ); // FIXME: preserve prefs + DISPLAY->SetVideoMode( DISPLAY->GetVideoModeParams() ); } break; } diff --git a/stepmania/src/arch/LowLevelWindow/LowLevelWindow_SDL.h b/stepmania/src/arch/LowLevelWindow/LowLevelWindow_SDL.h index 8d71f56aa5..0bd4062fc0 100644 --- a/stepmania/src/arch/LowLevelWindow/LowLevelWindow_SDL.h +++ b/stepmania/src/arch/LowLevelWindow/LowLevelWindow_SDL.h @@ -5,21 +5,17 @@ class LowLevelWindow_SDL: public LowLevelWindow { - bool Windowed; - int CurrentHeight, CurrentWidth, CurrentBPP; + RageDisplay::VideoModeParams CurrentParams; public: LowLevelWindow_SDL(); ~LowLevelWindow_SDL(); void *GetProcAddress(CString s); - bool SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ); + bool TryVideoMode( RageDisplay::VideoModeParams p, bool &bNewDeviceOut ); void SwapBuffers(); void Update(float fDeltaTime); - bool IsWindowed() const { return Windowed; } - int GetWidth() const { return CurrentWidth; } - int GetHeight() const { return CurrentHeight; } - int GetBPP() const { return CurrentBPP; } + RageDisplay::VideoModeParams GetVideoModeParams() const { return CurrentParams; } }; #undef ARCH_LOW_LEVEL_WINDOW #define ARCH_LOW_LEVEL_WINDOW LowLevelWindow_SDL