src/render/rScreen.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 *************************************************************************
00004 
00005 ArmageTron -- Just another Tron Lightcycle Game in 3D.
00006 Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
00007 
00008 **************************************************************************
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00023 
00024 ***************************************************************************
00025 
00026 */
00027 
00028     #include "rFont.h"
00029 
00030     #include "defs.h"
00031 
00032     #include <string>
00033     #include "rTexture.h"
00034     #include "rScreen.h"
00035     #include "rSysdep.h"
00036     #include "rConsole.h"
00037     #include "rViewport.h"
00038     #include "tConfiguration.h"
00039     #include "tRecorder.h"
00040     #include "tSysTime.h"
00041 
00042     #ifndef DEDICATED
00043 // #include "../network/nNetwork.h"
00044     #include "rGL.h"
00045     #include "rSDL.h"
00046 
00047     #ifdef POWERPAK_DEB
00048     #include <PowerPak/powerdraw>
00049     #endif
00050     #endif
00051 
00052     #ifndef SDL_OPENGL
00053     #ifndef DIRTY
00054     #define DIRTY
00055     #endif
00056     #endif
00057 
00058     #ifdef DEBUG
00059 //#ifdef WIN32
00060     #define FORCE_WINDOW
00061 //#endif
00062     #endif
00063 
00064 tCONFIG_ENUM( rResolution );
00065 tCONFIG_ENUM( rColorDepth );
00066 tCONFIG_ENUM( rVSync );
00067 
00068 SDL_Surface *sr_screen=NULL; // our window
00069 
00070     #ifndef DEDICATED
00071 static int default_texturemode = GL_LINEAR_MIPMAP_LINEAR;
00072     #endif
00073 
00074 rDisplayListUsage sr_useDisplayLists=rDisplayList_Off;
00075 
00076 static int width[ArmageTron_Custom+2]  = {0, 320, 320, 400, 512, 640, 800, 1024 , 1280, 1280, 1280, 1600, 1680, 2048,800,320};
00077 static int height[ArmageTron_Custom+2] = {0, 200, 240, 300, 384, 480, 600,  768 ,  800,  854, 1024, 1200, 1050, 1572,600,200};
00078 static REAL aspect[ArmageTron_Custom+2]= {1, 1  , 1  , 1  , 1  , 1  , 1  , 1    ,    1,    1, 1   ,    1,    1,    1,1,  1};
00079 
00080 int sr_screenWidth,sr_screenHeight;
00081 
00082 static tSettingItem<int>  at_ch("CUSTOM_SCREEN_HEIGHT"  , height[ArmageTron_Custom]);
00083 static tSettingItem<int>  at_cw("CUSTOM_SCREEN_WIDTH"   , width [ArmageTron_Custom]);
00084 static tSettingItem<REAL> at_ca("CUSTOM_SCREEN_ASPECT" , aspect[ArmageTron_Custom]);
00085 
00086     #define MAXEMERGENCY 6
00087 
00088 rScreenSettings lastSuccess(ArmageTron_640_480, false);
00089 
00090 /*
00091 std::ostream & operator << ( std::ostream & s, rScreenSize const & size )
00092 {
00093     return s;
00094 }
00095 
00096 std::istream & operator >> ( std::istream & s, rScreenSize const & size )
00097 {
00098     return s;
00099 }
00100 */
00101 
00102     #ifndef DEBUG
00103 static rScreenSettings em6(ArmageTron_320_240, false, ArmageTron_ColorDepth_16, true, false);
00104 static rScreenSettings em5(ArmageTron_320_240, false, ArmageTron_ColorDepth_Desktop, true, false);
00105 static rScreenSettings em4(ArmageTron_640_480, false,ArmageTron_ColorDepth_16);
00106 static rScreenSettings em3(ArmageTron_640_480, true, ArmageTron_ColorDepth_16);
00107 static rScreenSettings em2(ArmageTron_640_480, true, ArmageTron_ColorDepth_16, false);
00108 static rScreenSettings em1(ArmageTron_640_480);
00109 
00110 static rScreenSettings *emergency[MAXEMERGENCY+2]={ &lastSuccess, &lastSuccess, &em1, &em2, &em3 , &em4, &em5, &em6};
00111     #endif
00112 
00113     #ifdef DEBUG
00114 rScreenSettings currentScreensetting(ArmageTron_640_480);
00115     #else
00116 rScreenSettings currentScreensetting(sr_DesktopScreensizeSupported() ? ArmageTron_Desktop : ArmageTron_800_600, true);
00117     #endif
00118 
00119 bool sr_DesktopScreensizeSupported()
00120 {
00121 #ifndef DEDICATED
00122     SDL_version const & sdlVersion = *SDL_Linked_Version();
00123 
00124     return
00125         sdlVersion.major > 1 || sdlVersion.major == 1 &&
00126         ( sdlVersion.minor > 2 || sdlVersion.minor == 2 &&
00127           ( sdlVersion.patch >= 10 ) );
00128 #else
00129     return false;
00130 #endif
00131 }
00132 
00133 static int failed_attempts = 0;
00134 
00135 static tConfItem<rResolution> screenres("ARMAGETRON_SCREENMODE",currentScreensetting.res.res);
00136 static tConfItem<rResolution> screenresLast("ARMAGETRON_LAST_SCREENMODE",lastSuccess.res.res);
00137 
00138 static tConfItem<rResolution> winsize("ARMAGETRON_WINDOWSIZE",currentScreensetting.windowSize.res);
00139 static tConfItem<rResolution> winsizeLast("ARMAGETRON_LAST_WINDOWSIZE",lastSuccess.windowSize.res);
00140 
00141 static tConfItem<rVSync> vSync("ARMAGETRON_VSYNC",currentScreensetting.vSync);
00142 static tConfItem<rVSync> vSyncLast("ARMAGETRON_VSYNC_LAST",lastSuccess.vSync);
00143 
00144 static tConfItem<int> screenres_w("ARMAGETRON_SCREENMODE_W",currentScreensetting.res.width);
00145 static tConfItem<int> screenresLast_w("ARMAGETRON_LAST_SCREENMODE_W", lastSuccess.res.width);
00146 
00147 static tConfItem<int> winsize_w("ARMAGETRON_WINDOWSIZE_W",currentScreensetting.windowSize.width);
00148 static tConfItem<int> winsizeLast_w("ARMAGETRON_LAST_WINDOWSIZE_W",lastSuccess.windowSize.width);
00149 
00150 static tConfItem<int> screenres_h("ARMAGETRON_SCREENMODE_H",currentScreensetting.res.height);
00151 static tConfItem<int> screenresLast_h("ARMAGETRON_LAST_SCREENMODE_H", lastSuccess.res.height);
00152 
00153 // static tConfItem<rScreenSize> winsize_wh("ARMAGETRON_WINDOWSIZE_WH",currentScreensetting.windowSize);
00154 
00155 static tConfItem<int> winsize_h("ARMAGETRON_WINDOWSIZE_H",currentScreensetting.windowSize.height);
00156 static tConfItem<int> winsizeLast_h("ARMAGETRON_LAST_WINDOWSIZE_H",lastSuccess.windowSize.height);
00157 
00158 static tConfItem<bool> fs_ci("FULLSCREEN",currentScreensetting.fullscreen);
00159 static tConfItem<bool> fs_lci("LAST_FULLSCREEN",currentScreensetting.fullscreen);
00160 
00161 static tConfItem<rColorDepth> tc("COLORDEPTH",currentScreensetting.colorDepth);
00162 static tConfItem<rColorDepth> ltc("LAST_COLORDEPTH",lastSuccess.colorDepth);
00163 static tConfItem<rColorDepth> tzd("ZDEPTH",currentScreensetting.zDepth);
00164 static tConfItem<rColorDepth> ltzd("LAST_ZDEPTH",lastSuccess.zDepth);
00165 
00166     #ifdef DIRTY
00167     #ifdef SDL_OPENGL
00168 static tConfItem<bool> sdl("USE_SDL",currentScreensetting.useSDL);
00169 static tConfItem<bool> lsdl("LAST_USE_SDL",lastSuccess.useSDL);
00170     #endif
00171     #endif
00172 
00173 static tConfItem<bool> check_errors("CHECK_ERRORS",currentScreensetting.checkErrors);
00174 static tConfItem<bool> check_errorsl("LAST_CHECK_ERRORS",lastSuccess.checkErrors);
00175 
00176 static tConfItem<int> fa("FAILED_ATTEMPTS", failed_attempts);
00177 
00178 // *******************************************
00179 
00180 static tCallback *rPerFrameTask_anchor;
00181 
00182     #ifdef HAVE_LIBRUBY
00183 static tCallbackRuby * rPerFrameTaskRuby_anchor;
00184     #endif
00185 
00186 bool sr_True(){return true;}
00187 
00188 rPerFrameTask::rPerFrameTask(AA_VOIDFUNC *f):tCallback(rPerFrameTask_anchor, f){}
00189 void rPerFrameTask::DoPerFrameTasks(){
00190     // prevent console rendering, that can cause nasty recursions
00191     rNoAutoDisplayAtNewlineCallback noAutoDisplay( sr_True );
00192     Exec(rPerFrameTask_anchor);
00193 }
00194 
00195     #ifdef HAVE_LIBRUBY
00196 rPerFrameTaskRuby::rPerFrameTaskRuby()
00197         :tCallbackRuby(rPerFrameTaskRuby_anchor)
00198 {
00199 }
00200 
00201 void rPerFrameTaskRuby::DoPerFrameTasks(){
00202     rNoAutoDisplayAtNewlineCallback noAutoDisplay( sr_True );
00203     Exec(rPerFrameTaskRuby_anchor);
00204 }
00205     #endif
00206 
00207 
00208 
00209 // *******************************************
00210 
00211 static tCallbackString *RenderId_anchor;
00212 
00213 rRenderIdCallback::rRenderIdCallback(STRINGRETFUNC *f)
00214         :tCallbackString(RenderId_anchor, f){}
00215 tString rRenderIdCallback::RenderId(){return Exec(RenderId_anchor);}
00216 
00217 // *******************************************
00218 
00219 // *******************************************************************************************
00220 // *
00221 // *   rScreenSize
00222 // *
00223 // *******************************************************************************************
00228 // *******************************************************************************************
00229 
00230 rScreenSize::rScreenSize( int w, int h )
00231         :res( ArmageTron_Invalid ), width(w), height(h)
00232 {
00233 }
00234 
00235 // *******************************************************************************************
00236 // *
00237 // *   rScreenSize
00238 // *
00239 // *******************************************************************************************
00243 // *******************************************************************************************
00244 
00245 rScreenSize::rScreenSize( rResolution r )
00246         :res( r ), width(0), height(0)
00247 {
00248     UpdateSize();
00249 }
00250 
00251 // *******************************************************************************************
00252 // *
00253 // *   UpdateSize
00254 // *
00255 // *******************************************************************************************
00258 // *******************************************************************************************
00259 
00260 void rScreenSize::UpdateSize( void )
00261 {
00262     if ( res != ArmageTron_Invalid )
00263     {
00264         width = ::width[res];
00265         height = ::height[res];
00266         // res = ArmageTron_Invalid;
00267     }
00268 }
00269 
00270 // *******************************************************************************************
00271 // *
00272 // *   operator ==
00273 // *
00274 // *******************************************************************************************
00279 // *******************************************************************************************
00280 
00281 bool rScreenSize::operator ==( rScreenSize const & other ) const
00282 {
00283     return Compare( other ) == 0;
00284 }
00285 
00286 // *******************************************************************************************
00287 // *
00288 // *   operator !=
00289 // *
00290 // *******************************************************************************************
00295 // *******************************************************************************************
00296 
00297 bool rScreenSize::operator !=( rScreenSize const & other ) const
00298 {
00299     return Compare( other ) != 0;
00300 }
00301 
00302 // *******************************************************************************************
00303 // *
00304 // *   Compare
00305 // *
00306 // *******************************************************************************************
00311 // *******************************************************************************************
00312 
00313 int rScreenSize::Compare( rScreenSize const & other ) const
00314 {
00315     // desktop size dominates all
00316     if ( width == 0 && other.width != 0 )
00317         return 1;
00318     if ( other.width == 0 && width != 0 )
00319         return -1;
00320 
00321     if ( width < other.width )
00322         return -1;
00323     else if ( width > other.width )
00324         return 1;
00325 
00326     if ( height < other.height )
00327         return -1;
00328     else if ( height > other.height )
00329         return 1;
00330 
00331     /* res is not really a criterion, ignore it
00332     if ( res < other.res )
00333         return -1;
00334     else if ( res > other.res )
00335         return 1;
00336     */
00337 
00338     return 0;
00339 }
00340 
00341 
00342 // *******************************************************************************************
00343 // *
00344 // *   rScreenSettings
00345 // *
00346 // *******************************************************************************************
00354 // *******************************************************************************************
00355 
00356 rScreenSettings::rScreenSettings( rResolution r, bool fs, rColorDepth cd, bool sdl, bool ce )
00357         :res(r), windowSize(r), fullscreen(fs), colorDepth(cd), zDepth( ArmageTron_ColorDepth_Desktop ), useSDL(sdl), checkErrors(true), vSync( ArmageTron_VSync_Default ), aspect (1)
00358 {
00359     // special case for desktop resolution: window size of 640x480
00360     if ( r == ArmageTron_Desktop )
00361     {
00362         windowSize = rScreenSize( ArmageTron_640_480 );
00363     }
00364 }
00365 
00366 void sr_ReinitDisplay(){
00367     sr_ExitDisplay();
00368     if (!sr_InitDisplay()){
00369         tERR_ERROR("Oops. Failed to reinit video hardware. "
00370                    "Resetting to defaults..\n");
00371         exit(-1);
00372     }
00373 
00374 }
00375 
00376 
00377 // *******************************************
00378 
00379 
00380 
00381 // GL information
00382 
00383 tString gl_vendor;
00384 tString gl_renderer;
00385 tString gl_version;
00386 tString gl_extensions;
00387 
00388 bool software_renderer=false;
00389 bool last_software_renderer=false;
00390 
00391 static tConfItem<bool> lsr("SOFTWARE_RENDERER",last_software_renderer);
00392 
00393 tString lastError("Unknown");
00394 
00395     #ifndef DEDICATED
00396 static int countBits(unsigned int count)
00397 {
00398     int ret = 0;
00399     while (count)
00400     {
00401         ret    += count & 1;
00402         count >>= 1;
00403     }
00404 
00405     return ret;
00406 }
00407     #endif
00408 
00409     #ifndef DEDICATED
00410     #ifdef SDL_OPENGL
00411 // sets the number of vsync signals to wait for each frame
00412 static void sr_SetSwapControl( int frames, bool after = false )
00413 {
00414     bool success = false;
00415 
00416     #ifdef LINUX
00417     // set environment variable for the linux nvidia driver.
00418     // darn, changes to this can't be made while the program is running,
00419     // a restart is required.
00420     char hack[2];
00421     hack[0] = '0' + frames;
00422     hack[1] = 0;
00423     setenv( "__GL_SYNC_TO_VBLANK", hack, 1 );
00424     #endif
00425 
00426     #ifdef WIN32
00427     // special Windows code
00428     typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALFARPROC)( int );
00429     PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT = 0;
00430 
00431     {
00432         const char *extensions = gl_extensions;
00433 
00434         if( extensions && strstr( extensions, "WGL_EXT_swap_control" ) )
00435         {
00436             wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress( "wglSwapIntervalEXT" );
00437 
00438             if( wglSwapIntervalEXT )
00439             {
00440                 success = true;
00441                 if ( after )
00442                     wglSwapIntervalEXT( frames );
00443             }
00444         }
00445     }
00446     #endif
00447 
00448     // use SDL, requires 1.2.10
00449     #if SDL_VERSION_ATLEAST(1, 2, 10)
00450     if ( !success )
00451         SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, frames );
00452     #endif
00453 }
00454 
00455 static void sr_SetSwapControlAuto( bool after = false )
00456 {
00457     // requires SDL 1.2.10
00458     if ( tRecorder::IsRecording() )
00459     {
00460         // recordings are always done with VSync enabled
00461         sr_SetSwapControl( 1 );
00462     }
00463     else
00464     {
00465         switch (currentScreensetting.vSync)
00466         {
00467         case ArmageTron_VSync_On:
00468             sr_SetSwapControl( 1, after );
00469             break;
00470         case ArmageTron_VSync_Off:
00471         case ArmageTron_VSync_MotionBlur:
00472             sr_SetSwapControl( 0, after );
00473             break;
00474         case ArmageTron_VSync_Default:
00475             break;
00476         }
00477     }
00478 }
00479 
00480 static void sr_SetGLAttributes( int rDepth, int gDepth, int bDepth, int zDepth )
00481 {
00482     // SDL 1.1 required
00483     SDL_GL_SetAttribute( SDL_GL_RED_SIZE, rDepth );
00484     SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, gDepth );
00485     SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, bDepth );
00486     SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, zDepth );
00487     SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
00488 
00489     sr_SetSwapControlAuto();
00490 }
00491 
00492 // to be called after screen initialization
00493 static void sr_CompleteGLAttributes()
00494 {
00495     sr_SetSwapControlAuto( true );
00496 }
00497     #endif // SDL_OPENGL
00498     #endif // DEDICATED
00499 
00500 static bool lowlevel_sr_InitDisplay(){
00501     #ifndef DEDICATED
00502     rScreenSize & res = currentScreensetting.fullscreen ? currentScreensetting.res : currentScreensetting.windowSize;
00503 
00504     // update pixel aspect ratio
00505     if ( res.res != ArmageTron_Invalid )
00506         currentScreensetting.aspect = aspect[res.res];
00507 
00508     #ifndef DIRTY
00509     currentScreensetting.useSDL = true;
00510     #endif
00511     res.UpdateSize();
00512     sr_screenWidth = res.width;
00513     sr_screenHeight= res.height;
00514 
00515     if (!sr_screen)
00516     {
00517         int singleCD_R  = 5;
00518         int singleCD_G  = 5;
00519         int singleCD_B  = 5;
00520         int fullCD              = 16;
00521         int zDepth              = 16;
00522 
00523         switch (currentScreensetting.colorDepth)
00524         {
00525         case ArmageTron_ColorDepth_16:
00526             // parameters already set for this depth
00527             break;
00528         case ArmageTron_ColorDepth_Desktop:
00529             {
00530                 const SDL_VideoInfo* videoInfo     = SDL_GetVideoInfo( );
00531                 const SDL_PixelFormat* pixelFormat = videoInfo->vfmt;
00532                 fullCD                                 = pixelFormat->BitsPerPixel;
00533                 singleCD_R                         = countBits(pixelFormat->Rmask);
00534                 singleCD_G                         = countBits(pixelFormat->Gmask);
00535                 singleCD_B                         = countBits(pixelFormat->Bmask);
00536             }
00537             break;
00538         case ArmageTron_ColorDepth_32:
00539             singleCD_R  = 8;
00540             singleCD_G  = 8;
00541             singleCD_B  = 8;
00542             fullCD              = 24;
00543             zDepth              = 32;
00544             break;
00545         }
00546 
00547         switch ( currentScreensetting.zDepth )
00548         {
00549         case ArmageTron_ColorDepth_16: zDepth = 16; break;
00550         case ArmageTron_ColorDepth_32: zDepth = 32; break;
00551         default: break;
00552         }
00553 
00554     #ifdef SDL_OPENGL
00555         if (currentScreensetting.useSDL)
00556         {
00557             sr_SetGLAttributes( singleCD_R, singleCD_G, singleCD_B, zDepth );
00558         }
00559     #else
00560         currentScreensetting.useSDL = false;
00561     #endif
00562 
00563 
00564 
00565         /*
00566           #ifdef POWERPAK_DEB
00567           PD_SetGFXMode(sr_screenWidth, sr_screenHeight, 32, PD_DEFAULT);
00568           sr_screen=DoubleBuffer;
00569           #else
00570         */
00571 
00572         int attrib;
00573 
00574     #ifdef SDL_OPENGL
00575         if (currentScreensetting.useSDL)
00576         {
00577             // SDL 1.1
00578     #ifndef FORCE_WINDOW
00579             if (currentScreensetting.fullscreen)
00580                 attrib=SDL_OPENGL | SDL_FULLSCREEN;
00581             else
00582     #endif
00583                 attrib=SDL_OPENGL;
00584         }
00585         else
00586     #endif
00587         {
00588     #ifndef FORCE_WINDOW
00589             if (currentScreensetting.fullscreen)
00590                 attrib=SDL_DOUBLEBUF | SDL_SWSURFACE | SDL_FULLSCREEN;
00591             else
00592     #endif
00593                 attrib=SDL_DOUBLEBUF | SDL_SWSURFACE;
00594         }
00595 
00596     #ifdef FORCE_WINDOW
00597     #ifdef WIN32
00598         //              sr_screenWidth  = 400;
00599         //              sr_screenHeight = 300;
00600     #else
00601         //              sr_screenWidth  = 640;
00602         //              sr_screenHeight = 480;
00603     #endif
00604     #endif
00605         int CD = fullCD;
00606 
00607         if (currentScreensetting.checkErrors)
00608         {
00609             // check if the video mode should be OK:
00610             CD = SDL_VideoModeOK
00611                  (sr_screenWidth, sr_screenHeight,   fullCD,
00612                   attrib);
00613 
00614             // if not quite right
00615             if (CD < fullCD){
00616                 // check if the other fs/windowed mode is better
00617                 int CD_fsinv = SDL_VideoModeOK
00618                                (sr_screenWidth, sr_screenHeight,   fullCD,
00619                                 attrib^SDL_FULLSCREEN);
00620 
00621                 if (CD_fsinv > fullCD){
00622                     // yes! change the mode
00623                     currentScreensetting.fullscreen=!currentScreensetting.fullscreen;
00624                     attrib ^= SDL_FULLSCREEN;
00625                     CD = CD_fsinv;
00626                 }
00627             }
00628 
00629             if (CD < fullCD && currentScreensetting.colorDepth != ArmageTron_ColorDepth_16)
00630             {
00631                 currentScreensetting.colorDepth = ArmageTron_ColorDepth_16;
00632 
00633     #ifdef SDL_OPENGL
00634                 if (currentScreensetting.useSDL)
00635                 {
00636                     sr_SetGLAttributes( 5, 5, 5, 16 );
00637                 }
00638     #endif
00639             }
00640         }
00641 
00642         // determine desktop resolution
00643         static int sr_desktopWidth = 0, sr_desktopHeight = 0;
00644         if ( sr_desktopWidth == 0 && !sr_screen )
00645         {
00646             // select sane defaults in case the following operation fails
00647             sr_desktopWidth = 640;
00648             sr_desktopHeight = 480;
00649 
00650             if ( sr_DesktopScreensizeSupported() )
00651             {
00652                 sr_screen=SDL_SetVideoMode( 0, 0, CD, attrib );
00653                 if ( sr_screen )
00654                 {
00655                     sr_desktopWidth = sr_screen->w;
00656                     sr_desktopHeight = sr_screen->h;
00657                 }
00658             }
00659         }
00660 
00661         // if desktop resolution was selected, pick it
00662         if ( sr_screenWidth + sr_screenHeight == 0 )
00663         {
00664             sr_screenWidth = sr_desktopWidth;
00665             sr_screenHeight = sr_desktopHeight;
00666         }
00667 
00668         if ( (sr_screen=SDL_SetVideoMode
00669                         (sr_screenWidth, sr_screenHeight,   CD,
00670                          attrib))
00671                 == NULL)
00672         {
00673             if((sr_screen=SDL_SetVideoMode
00674                           (sr_screenWidth, sr_screenHeight,    CD,
00675                            attrib^SDL_FULLSCREEN))==NULL )
00676             {
00677                 lastError.Clear();
00678                 lastError << "Couldn't set video mode: ";
00679                 lastError << SDL_GetError();
00680                 std::cerr << lastError << '\n';
00681                 return false;
00682             }
00683             else
00684             {
00685                 currentScreensetting.fullscreen=!currentScreensetting.fullscreen;
00686             }
00687         }
00688 
00689         // MacOSX SDL 1.2.4 crashes if we SetCaption after switch to fullscreen. (fixed in 1.2.5)
00690     #ifdef MACOSX
00691         if(!currentScreensetting.fullscreen)
00692     #endif
00693         {
00694             tOutput o("Armagetron Advanced");
00695             tString s;
00696             s << o;
00697             SDL_WM_SetCaption(s, s);
00698         }
00699 
00700         sr_CompleteGLAttributes();
00701 
00702         SDL_EnableUNICODE(1);
00703     }
00704 
00705     #ifdef DIRTY
00706     if (!currentScreensetting.useSDL)
00707         if(!rSysDep::InitGL()) return false;
00708     #endif
00709 
00710     #ifndef DEDICATED
00711     gl_vendor.Clear();
00712     gl_renderer.Clear();
00713     gl_version.Clear();
00714     gl_extensions.Clear();
00715     renderer_identification.Clear();
00716 
00717     gl_vendor     << reinterpret_cast<const char *>(glGetString(GL_VENDOR));
00718     gl_renderer   << reinterpret_cast<const char *>(glGetString(GL_RENDERER));
00719     gl_version    << reinterpret_cast<const char *>(glGetString(GL_VERSION));
00720     gl_extensions << reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
00721 
00722     #ifndef WIN32
00723     if(!strstr(gl_renderer,"Voodoo3"))
00724     #endif
00725         if(currentScreensetting.fullscreen)
00726             SDL_ShowCursor(0);
00727         else
00728             SDL_ShowCursor(1);
00729 
00730     #ifdef WIN32
00731     renderer_identification << "WIN32 ";
00732     #else
00733     #ifdef MACOSX
00734     renderer_identification << "MACOSX ";
00735     #else
00736     renderer_identification << "LINUX ";
00737     #endif
00738     #endif
00739     renderer_identification << rRenderIdCallback::RenderId() << ' ';
00740     #ifdef SDL_OPENGL
00741     renderer_identification << "SDL 1.2\n";
00742     renderer_identification << "USE_SDL=" << currentScreensetting.useSDL
00743     << '\n';
00744     #else
00745     renderer_identification << "SDL 1.0\n";
00746     #endif
00747     renderer_identification << "CD=" << currentScreensetting.colorDepth  << '\n';
00748     renderer_identification << "FS=" << currentScreensetting.fullscreen  << '\n';
00749     renderer_identification << "GL_VENDOR=" << gl_vendor   << '\n';
00750     renderer_identification << "GL_RENDERER=" << gl_renderer << '\n';
00751     renderer_identification << "GL_VERSION=" << gl_version  << '\n';
00752     #endif
00753 
00754     if (// test for Windows software GL (be a little flexible...)
00755         (
00756             strstr(gl_vendor,"icrosoft") || strstr(gl_vendor,"SGI")
00757         )
00758         && strstr(gl_renderer,"eneric")
00759     )
00760         software_renderer=true;
00761 
00762     if ( // test for Mesa software GL
00763         strstr(gl_vendor,"rian") && strstr(gl_renderer,"X11") &&
00764         strstr(gl_renderer,"esa")
00765     )
00766         software_renderer=true;
00767 
00768     if ( // test for GLX software GL
00769         strstr(gl_renderer,"GLX") &&
00770         strstr(gl_renderer,"ndirect") &&
00771         strstr(gl_renderer,"esa")
00772     )
00773         software_renderer=true;
00774 
00775     // disable storage of non-alpha textures on Savage MX
00776     if ( strstr( gl_renderer, "SavageMX" ) )
00777     {
00778         rISurfaceTexture::storageHack_ = true;
00779     }
00780 
00781     // fonts look best in bilinear filtering, no mipmaps
00782     if ( rTextureGroups::TextureMode[rTextureGroups::TEX_FONT] > GL_LINEAR )
00783         rTextureGroups::TextureMode[rTextureGroups::TEX_FONT] = GL_LINEAR;
00784 
00785     // disable trilinear filtering for ATI cards
00786     if ( strstr( gl_vendor, "ATI" ) )
00787     {
00788         default_texturemode = GL_LINEAR_MIPMAP_NEAREST;
00789     }
00790 
00791     // wait for activation if we were ALT-Tabbed away:
00792     while ( (SDL_GetAppState() & SDL_APPACTIVE) == 0)
00793     {
00794         SDL_Delay(100);
00795         SDL_PumpEvents();
00796     }
00797 
00798     if (software_renderer && !last_software_renderer && !tRecorder::IsPlayingBack())
00799         sr_LoadDefaultConfig();
00800 
00801     last_software_renderer=software_renderer;
00802 
00803 
00804     // wait for activation if we were ALT-Tabbed away:
00805     while ( (SDL_GetAppState() & SDL_APPACTIVE) == 0)
00806     {
00807         SDL_Delay(100);
00808         SDL_PumpEvents();
00809     }
00810 
00811     sr_ResetRenderState(true);
00812 
00813     rCallbackAfterScreenModeChange::Exec();
00814     #endif
00815     return true;
00816 }
00817 
00818 extern bool cycleprograminited;
00819 
00820 bool sr_InitDisplay(){
00821     cycleprograminited = false;
00822     while (failed_attempts <= MAXEMERGENCY+1)
00823     {
00824     #ifndef DEBUG
00825         if (failed_attempts)
00826             currentScreensetting = *emergency[failed_attempts];
00827 
00828         failed_attempts++;
00829         st_SaveConfig();
00830 
00831         //      std::cout << failed_attempts << "\n";
00832         //      std::cout.flush();
00833     #endif
00834 
00835     #ifdef MACOSX
00836         // init the screen once in windowed mode
00837         static bool first = true;
00838         if ( first && currentScreensetting.fullscreen )
00839         {
00840             first = false;
00841             currentScreensetting.fullscreen = false;
00842 
00843             sr_LockSDL();
00844             if (lowlevel_sr_InitDisplay())
00845             {
00846                 sr_ExitDisplay();
00847             }
00848             sr_UnlockSDL();
00849 
00850             currentScreensetting.fullscreen = true;
00851         }
00852     #endif
00853 
00854         sr_LockSDL();
00855         if (lowlevel_sr_InitDisplay())
00856         {
00857             lastSuccess=currentScreensetting;
00858             sr_UnlockSDL();
00859             return true;
00860         }
00861 
00862         st_SaveConfig();
00863 
00864         if (lowlevel_sr_InitDisplay())
00865         {
00866             lastSuccess=currentScreensetting;
00867             sr_UnlockSDL();
00868             return true;
00869         }
00870         sr_UnlockSDL();
00871 
00872 
00873     }
00874 
00875     failed_attempts = 1;
00876     st_SaveConfig();
00877 
00878     tERR_ERROR("\nSorry, played all my cards trying to "
00879                "initialize your video system.\n"
00880                << tOutput("$program_name") << " won't run on your computer. Reason:\n\n"
00881                << lastError
00882                << "\n\nI'll try again from the beginning, but the "
00883                << "chances of success are minimal.\n"
00884               );
00885 
00886     return false;
00887 }
00888 
00889 
00890 void sr_ExitDisplay(){
00891     #ifndef DEDICATED
00892     rCallbackBeforeScreenModeChange::Exec();
00893 
00894     #ifdef DIRTY
00895     rSysDep::ExitGL();
00896     #endif
00897 
00898     if (sr_screen){
00899         failed_attempts = 0;
00900         st_SaveConfig();
00901 
00902         sr_LockSDL();
00903         // z-man: according to man SDL_SetVideoSurface, screen should not bee freed.
00904         // SDL_FreeSurface(sr_screen);
00905         sr_screen=NULL;
00906         sr_UnlockSDL();
00907         //SDL_Quit();
00908     }
00909     #endif
00910 }
00911 
00912 bool    sr_alphaBlend=true;
00913 bool    sr_glOut=true;
00914 bool    sr_smoothShading=true;
00915 
00916 
00917 int sr_floorMirror=0;
00918 int sr_floorDetail=rFLOOR_TEXTURE;
00919 bool sr_highRim=true;
00920 bool sr_upperSky=false;
00921 bool sr_lowerSky=false;
00922 bool sr_skyWobble=true;
00923 bool sr_dither=true;
00924 bool sr_infinityPlane=false;
00925 bool sr_laggometer=true;
00926 bool sr_predictObjects=false;
00927 bool sr_texturesTruecolor=false;
00928 
00929 bool sr_textOut=false;
00930 bool sr_FPSOut=true;
00931 
00932 bool sr_keepWindowActive=false;
00933 
00934 tString renderer_identification;
00935 
00936 void sr_LoadDefaultConfig(){
00937 
00938     // High detail defaults; no problem for your ordinary 3d-card.
00939     sr_alphaBlend=true;
00940     sr_useDisplayLists=rDisplayList_Off;
00941     sr_textOut=true;
00942     sr_dither=true;
00943     sr_smoothShading=true;
00944     int i;
00945     #ifndef DEDICATED
00946     for (i=rTextureGroups::TEX_GROUPS-1;i>=0;i--)
00947         rTextureGroups::TextureMode[i]=default_texturemode;
00948 
00949     // fonts look best in bilinear filtering, no mipmaps
00950     rTextureGroups::TextureMode[rTextureGroups::TEX_FONT]=GL_LINEAR;
00951     #endif
00952     sr_floorDetail=rFLOOR_TWOTEXTURE;
00953     sr_floorMirror=rMIRROR_OFF;
00954     sr_infinityPlane=false;
00955     sr_lowerSky=false;
00956     sr_upperSky=false;
00957     sr_keepWindowActive=false;
00958     rSysDep::swapMode_=rSysDep::rSwap_glFinish;
00959 
00960     if (software_renderer){
00961         // A software renderer! Poor soul. Set low details:
00962         for (i=rTextureGroups::TEX_GROUPS-1;i>=0;i--)
00963             rTextureGroups::TextureMode[i]=-1;
00964 
00965     #ifndef DEDICATED
00966         rTextureGroups::TextureMode[rTextureGroups::TEX_OBJ]=GL_NEAREST_MIPMAP_NEAREST;
00967         rTextureGroups::TextureMode[rTextureGroups::TEX_FONT]=GL_NEAREST_MIPMAP_NEAREST;
00968     #endif
00969 
00970         sr_highRim=false;
00971         sr_dither=false;
00972         sr_alphaBlend=false;
00973         sr_smoothShading=true; // smooth shading does not slow down the
00974         // two tested renderers; leave it it.
00975         sr_floorDetail=rFLOOR_GRID;
00976         sr_floorMirror=rMIRROR_OFF;
00977     }
00978     else if(strstr(gl_vendor,"3Dfx")){
00979         //workaround for 3dfx renderer: aliasing must be turned on
00980         //sr_lineAntialias=rFEAT_OFF;
00981     }
00982     else if(strstr(gl_vendor,"NVIDIA")){
00983         // infinity , display lists and glFlush swapping work for NVIDIA
00984         sr_infinityPlane=true;
00985         sr_useDisplayLists=rDisplayList_CAC;
00986         rSysDep::swapMode_=rSysDep::rSwap_glFlush;
00987     }
00988     #ifdef MACOSX
00989     else if(strstr(gl_vendor,"ATI")){
00990         // glFlush swapping work for ATI on the mac
00991         rSysDep::swapMode_=rSysDep::rSwap_glFlush;
00992     }
00993     #endif
00994     else if(strstr(gl_vendor,"Matrox")){
00995         sr_floorDetail = rFLOOR_TEXTURE;  // double textured floor does not work
00996     }
00997 }
00998 
00999 void sr_ResetRenderState(bool menu){
01000     if(!sr_glOut)
01001         return;
01002     #ifndef DEDICATED
01003 
01004     // Z-Buffering and perspective correction
01005 
01006     if (menu){
01007         glDisable(GL_DEPTH_TEST);
01008         glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
01009         glViewport (0, 0, GLsizei(sr_screenWidth), GLsizei(sr_screenHeight));
01010     }
01011     else{
01012         glEnable(GL_DEPTH_TEST);
01013         glDepthFunc(GL_LEQUAL);
01014     }
01015 
01016     if (sr_dither)
01017         glEnable(GL_DITHER);
01018     else
01019         glDisable(GL_DITHER);
01020 
01021     glDisable(GL_LIGHTING);
01022 
01023     // disable texture mapping (selecting textures will reactivate it)
01024 
01025     //  glDisable(GL_TEXTURE);
01026     glDisable(GL_TEXTURE_2D);
01027 
01028 
01029     // flat or smooth shading
01030     if (sr_smoothShading)
01031         glShadeModel(GL_SMOOTH);
01032     else
01033         glShadeModel(GL_FLAT);
01034 
01035     // alpha blending
01036     if (sr_alphaBlend){
01037         glEnable(GL_ALPHA_TEST);
01038         glAlphaFunc(GL_GREATER,0);
01039         glEnable(GL_BLEND);
01040         glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
01041     }
01042     else{
01043         glDisable(GL_ALPHA_TEST);
01044         glDisable(GL_BLEND);
01045     }
01046 
01047     // reset matrices
01048     glMatrixMode(GL_TEXTURE);
01049     glLoadIdentity();
01050 
01051     glMatrixMode(GL_PROJECTION);
01052     glLoadIdentity();
01053 
01054     glMatrixMode(GL_MODELVIEW);
01055     glLoadIdentity();
01056     #endif
01057 }
01058 
01059 
01060 /*
01061 static uMenuItemFunction apply
01062 (&sg_screenMenu_mode,"Apply Changes",
01063 "This activates the changes to the resolution and fullscreen/windowed mode "
01064 "made above. This does not work on all systems; exit and reenter Armagetron "
01065 "instead if you experience problems.",
01066  sr_ReinitDisplay);
01067 */
01068 
01069 
01070 
01071 
01072 
01073 //static bool offs=false;
01074 
01075 void sr_DepthOffset(bool offset){
01076     // return;
01077     //  if(offset!=offs){
01078     //offs=offset;
01079     #ifndef DEDICATED
01080     if (offset){
01081         //glMatrixMode(GL_PROJECTION);
01082         //glScalef(.9,.9,.9);
01083         glPolygonOffset(-2,-5);
01084         glEnable(GL_POLYGON_OFFSET_LINE);
01085         glEnable(GL_POLYGON_OFFSET_POINT);
01086         glEnable(GL_POLYGON_OFFSET_FILL);
01087     }
01088     else{
01089         glPolygonOffset(0,0);
01090         glDisable(GL_POLYGON_OFFSET_POINT);
01091         glDisable(GL_POLYGON_OFFSET_LINE);
01092         glDisable(GL_POLYGON_OFFSET_FILL);
01093         //glMatrixMode(GL_PROJECTION);
01094         //glScalef(1/.9,1/.9,1/.9);
01095     }
01096     //  }
01097     #endif
01098 }
01099 
01100 // set activation staus
01101 void sr_Activate(bool active)
01102 {
01103     #ifndef DEDICATED
01104     if ( !currentScreensetting.fullscreen && !active && sr_keepWindowActive )
01105     {
01106         sr_glOut=!active;
01107     }
01108     else
01109     {
01110         sr_glOut=active;
01111     }
01112 
01113     // unload textures and stuff if rendering gets disabled
01114     if (!sr_glOut)
01115         rCallbackBeforeScreenModeChange::Exec();
01116 
01117     // Jonathans fullscreen bugfix.
01118     // z-man's ammendmend: apparently, doing this in Linux is painful as well.
01119     // Only on Windows, you get a deactivation event when you ALT-TAB away
01120     // from th application, then iconification is the right thing to do.
01121     // On Linux at least, there is no standard alt-tab for fullscreen applications.
01122 #ifdef WIN32
01123     if ( currentScreensetting.fullscreen && !active )
01124     {
01125         SDL_WM_IconifyWindow();
01126     }
01127     #endif
01128     #endif
01129 }
01130 
01131 //**************************************
01132 //** Screen mode callbacks            **
01133 //**************************************
01134 
01135 
01136 static tCallback *sr_BeforeAnchor;
01137 
01138 rCallbackBeforeScreenModeChange::rCallbackBeforeScreenModeChange(AA_VOIDFUNC *f)
01139         :tCallback(sr_BeforeAnchor, f){}
01140 
01141 void rCallbackBeforeScreenModeChange::Exec()
01142 {
01143     tCallback::Exec(sr_BeforeAnchor);
01144 }
01145 
01146 static tCallback *sr_AfterAnchor;
01147 
01148 rCallbackAfterScreenModeChange::rCallbackAfterScreenModeChange(AA_VOIDFUNC *f)
01149         :tCallback(sr_AfterAnchor, f){}
01150 
01151 void rCallbackAfterScreenModeChange::Exec()
01152 {
01153     tCallback::Exec(sr_AfterAnchor);
01154 }
01155 

Generated on Sat Mar 15 22:55:53 2008 for Armagetron Advanced by  doxygen 1.5.4