1 /*
2 
3 *************************************************************************
4 
5 ArmageTron -- Just another Tron Lightcycle Game in 3D.
6 Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
7 
8 **************************************************************************
9 
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23 
24 ***************************************************************************
25 
26 */
27 
28 #include "rFont.h"
29 
30 #include "defs.h"
31 
32 #include <string>
33 #include "rTexture.h"
34 #include "rScreen.h"
35 #include "rSysdep.h"
36 #include "rConsole.h"
37 #include "rViewport.h"
38 #include "tConfiguration.h"
39 #include "tSysTime.h"
40 
41 #ifndef DEDICATED
42 // #include "../network/nNetwork.h"
43 #include "rGL.h"
44 #include "rSDL.h"
45 
46 #ifdef POWERPAK_DEB
47 #include <PowerPak/powerdraw>
48 #endif
49 #endif
50 
51 #ifndef SDL_OPENGL
52 #ifndef DIRTY
53 #define DIRTY
54 #endif
55 #endif
56 
57 #ifdef DEBUG
58 //#ifdef WIN32
59 #define FORCE_WINDOW
60 //#endif
61 #endif
62 
63 tCONFIG_ENUM( rResolution );
64 tCONFIG_ENUM( rColorDepth );
65 
66 SDL_Surface *sr_screen=NULL; // our window
67 
68 #ifndef DEDICATED
69 static int default_texturemode = GL_LINEAR_MIPMAP_LINEAR;
70 #endif
71 
72 rDisplayListUsage sr_useDisplayLists=rDisplayList_Off;
73 bool              sr_blacklistDisplayLists=false;
74 
75 static int width[ArmageTron_Custom+2]  = {0, 320, 320, 400, 512, 640, 800, 1024	, 1280, 1280, 1280, 1600, 1680, 2048,800,320};
76 static int height[ArmageTron_Custom+2] = {0, 200, 240, 300, 384, 480, 600,  768	,  800,  854, 1024, 1200, 1050, 1572,600,200};
77 static REAL aspect[ArmageTron_Custom+2]= {1, 1	, 1  , 1  , 1  , 1  , 1	 , 1	,    1,    1, 1   ,    1,    1,    1,1,  1};
78 
79 int sr_screenWidth,sr_screenHeight;
80 
81 static tSettingItem<int>  at_ch("CUSTOM_SCREEN_HEIGHT"	, height[ArmageTron_Custom]);
82 static tSettingItem<int>  at_cw("CUSTOM_SCREEN_WIDTH" 	, width	[ArmageTron_Custom]);
83 static tSettingItem<REAL> at_ca("CUSTOM_SCREEN_ASPECT" , aspect[ArmageTron_Custom]);
84 
85 #define MAXEMERGENCY 6
86 
87 rScreenSettings lastSuccess(ArmageTron_640_480, false);
88 
89 /*
90 std::ostream & operator << ( std::ostream & s, rScreenSize const & size )
91 {
92     return s;
93 }
94 
95 std::istream & operator >> ( std::istream & s, rScreenSize const & size )
96 {
97     return s;
98 }
99 */
100 
101 #ifndef DEBUG
102 static rScreenSettings em6(ArmageTron_320_240, false, ArmageTron_ColorDepth_16, true, false);
103 static rScreenSettings em5(ArmageTron_320_240, false, ArmageTron_ColorDepth_Desktop, true, false);
104 static rScreenSettings em4(ArmageTron_640_480, false,ArmageTron_ColorDepth_16);
105 static rScreenSettings em3(ArmageTron_640_480, true, ArmageTron_ColorDepth_16);
106 static rScreenSettings em2(ArmageTron_640_480, true, ArmageTron_ColorDepth_16, false);
107 static rScreenSettings em1(ArmageTron_640_480);
108 
109 static rScreenSettings *emergency[MAXEMERGENCY+2]={ &lastSuccess, &lastSuccess, &em1, &em2, &em3 , &em4, &em5, &em6};
110 #endif
111 
112 #ifdef DEBUG
113 rScreenSettings currentScreensetting(ArmageTron_640_480);
114 #else
115 rScreenSettings currentScreensetting(sr_DesktopScreensizeSupported() ? ArmageTron_Desktop : ArmageTron_800_600, true);
116 #endif
117 
sr_DesktopScreensizeSupported()118 bool sr_DesktopScreensizeSupported()
119 {
120 #ifndef DEDICATED
121     SDL_version const & sdlVersion = *SDL_Linked_Version();
122 
123     return
124     sdlVersion.major > 1 ||
125     ( sdlVersion.major == 1 &&
126       ( sdlVersion.minor > 2 ||
127         ( sdlVersion.minor == 2 &&
128           ( sdlVersion.patch >= 10 ) ) ) );
129 #else
130     return false;
131 #endif
132 }
133 
134 static int failed_attempts = 0;
135 
136 static tConfItem<rResolution> screenres("ARMAGETRON_SCREENMODE",currentScreensetting.res.res);
137 static tConfItem<rResolution> screenresLast("ARMAGETRON_LAST_SCREENMODE",lastSuccess.res.res);
138 
139 static tConfItem<rResolution> winsize("ARMAGETRON_WINDOWSIZE",currentScreensetting.windowSize.res);
140 static tConfItem<rResolution> winsizeLast("ARMAGETRON_LAST_WINDOWSIZE",lastSuccess.windowSize.res);
141 
142 static tConfItem<int> screenres_w("ARMAGETRON_SCREENMODE_W",currentScreensetting.res.width);
143 static tConfItem<int> screenresLast_w("ARMAGETRON_LAST_SCREENMODE_W", lastSuccess.res.width);
144 
145 static tConfItem<int> winsize_w("ARMAGETRON_WINDOWSIZE_W",currentScreensetting.windowSize.width);
146 static tConfItem<int> winsizeLast_w("ARMAGETRON_LAST_WINDOWSIZE_W",lastSuccess.windowSize.width);
147 
148 static tConfItem<int> screenres_h("ARMAGETRON_SCREENMODE_H",currentScreensetting.res.height);
149 static tConfItem<int> screenresLast_h("ARMAGETRON_LAST_SCREENMODE_H", lastSuccess.res.height);
150 
151 // static tConfItem<rScreenSize> winsize_wh("ARMAGETRON_WINDOWSIZE_WH",currentScreensetting.windowSize);
152 
153 static tConfItem<int> winsize_h("ARMAGETRON_WINDOWSIZE_H",currentScreensetting.windowSize.height);
154 static tConfItem<int> winsizeLast_h("ARMAGETRON_LAST_WINDOWSIZE_H",lastSuccess.windowSize.height);
155 
156 static tConfItem<bool> fs_ci("FULLSCREEN",currentScreensetting.fullscreen);
157 static tConfItem<bool> fs_lci("LAST_FULLSCREEN",currentScreensetting.fullscreen);
158 
159 static tConfItem<rColorDepth> tc("COLORDEPTH",currentScreensetting.colorDepth);
160 static tConfItem<rColorDepth> ltc("LAST_COLORDEPTH",lastSuccess.colorDepth);
161 static tConfItem<rColorDepth> tzd("ZDEPTH",currentScreensetting.zDepth);
162 static tConfItem<rColorDepth> ltzd("LAST_ZDEPTH",lastSuccess.zDepth);
163 
164 #ifdef DIRTY
165 #ifdef SDL_OPENGL
166 static tConfItem<bool> sdl("USE_SDL",currentScreensetting.useSDL);
167 static tConfItem<bool> lsdl("LAST_USE_SDL",lastSuccess.useSDL);
168 #endif
169 #endif
170 
171 static tConfItem<bool> check_errors("CHECK_ERRORS",currentScreensetting.checkErrors);
172 static tConfItem<bool> check_errorsl("LAST_CHECK_ERRORS",lastSuccess.checkErrors);
173 
174 static tConfItem<int> fa("FAILED_ATTEMPTS", failed_attempts);
175 
176 // *******************************************
177 
178 static tCallback *rPerFrameTask_anchor;
179 
sr_True()180 bool sr_True(){return true;}
181 
rPerFrameTask(VOIDFUNC * f)182 rPerFrameTask::rPerFrameTask(VOIDFUNC *f):tCallback(rPerFrameTask_anchor, f){}
DoPerFrameTasks()183 void rPerFrameTask::DoPerFrameTasks(){
184     // prevent console rendering, that can cause nasty recursions
185     rNoAutoDisplayAtNewlineCallback noAutoDisplay( sr_True );
186     Exec(rPerFrameTask_anchor);
187 }
188 
189 
190 // *******************************************
191 
192 static tCallbackString *RenderId_anchor;
193 
rRenderIdCallback(STRINGRETFUNC * f)194 rRenderIdCallback::rRenderIdCallback(STRINGRETFUNC *f)
195         :tCallbackString(RenderId_anchor, f){}
RenderId()196 tString rRenderIdCallback::RenderId(){return Exec(RenderId_anchor);}
197 
198 // *******************************************
199 
200 // *******************************************************************************************
201 // *
202 // *   rScreenSize
203 // *
204 // *******************************************************************************************
205 //!
206 //!        @param  w   screen width
207 //!        @param  h  screen height
208 //!
209 // *******************************************************************************************
210 
rScreenSize(int w,int h)211 rScreenSize::rScreenSize( int w, int h )
212         :res( ArmageTron_Invalid ), width(w), height(h)
213 {
214 }
215 
216 // *******************************************************************************************
217 // *
218 // *   rScreenSize
219 // *
220 // *******************************************************************************************
221 //!
222 //!        @param  r
223 //!
224 // *******************************************************************************************
225 
rScreenSize(rResolution r)226 rScreenSize::rScreenSize( rResolution r )
227         :res( r ), width(0), height(0)
228 {
229     UpdateSize();
230 }
231 
232 // *******************************************************************************************
233 // *
234 // *   UpdateSize
235 // *
236 // *******************************************************************************************
237 //!
238 //!
239 // *******************************************************************************************
240 
UpdateSize(void)241 void rScreenSize::UpdateSize( void )
242 {
243     if ( res != ArmageTron_Invalid )
244     {
245         width = ::width[res];
246         height = ::height[res];
247         // res = ArmageTron_Invalid;
248     }
249 }
250 
251 // *******************************************************************************************
252 // *
253 // *   operator ==
254 // *
255 // *******************************************************************************************
256 //!
257 //!        @param  other   size to compare with
258 //!        @return true iff equal
259 //!
260 // *******************************************************************************************
261 
operator ==(rScreenSize const & other) const262 bool rScreenSize::operator ==( rScreenSize const & other ) const
263 {
264     return Compare( other ) == 0;
265 }
266 
267 // *******************************************************************************************
268 // *
269 // *   operator !=
270 // *
271 // *******************************************************************************************
272 //!
273 //!        @param  other   size to compare with
274 //!        @return  true iff not equal
275 //!
276 // *******************************************************************************************
277 
operator !=(rScreenSize const & other) const278 bool rScreenSize::operator !=( rScreenSize const & other ) const
279 {
280     return Compare( other ) != 0;
281 }
282 
283 // *******************************************************************************************
284 // *
285 // *   Compare
286 // *
287 // *******************************************************************************************
288 //!
289 //!        @param  other   size to compare with
290 //!        @return         0 if eqal, -1 if this is smaller, +1 if other is smaller
291 //!
292 // *******************************************************************************************
293 
Compare(rScreenSize const & other) const294 int rScreenSize::Compare( rScreenSize const & other ) const
295 {
296     // desktop size dominates all
297     if ( width == 0 && other.width != 0 )
298         return 1;
299     if ( other.width == 0 && width != 0 )
300         return -1;
301 
302     if ( width < other.width )
303         return -1;
304     else if ( width > other.width )
305         return 1;
306 
307     if ( height < other.height )
308         return -1;
309     else if ( height > other.height )
310         return 1;
311 
312     /* res is not really a criterion, ignore it
313     if ( res < other.res )
314         return -1;
315     else if ( res > other.res )
316         return 1;
317     */
318 
319     return 0;
320 }
321 
322 
323 // *******************************************************************************************
324 // *
325 // *   rScreenSettings
326 // *
327 // *******************************************************************************************
328 //!
329 //!        @param  r   the resolution
330 //!        @param  fs  fullscreen flag
331 //!        @param  cd  color depth
332 //!        @param  sdl use clean sdl initialization
333 //!        @param  ce  check for errors
334 //!
335 // *******************************************************************************************
336 
rScreenSettings(rResolution r,bool fs,rColorDepth cd,bool sdl,bool ce)337 rScreenSettings::rScreenSettings( rResolution r, bool fs, rColorDepth cd, bool sdl, bool ce )
338         :res(r), windowSize(r), fullscreen(fs), colorDepth(cd), zDepth( ArmageTron_ColorDepth_Desktop ), useSDL(sdl), checkErrors(true), aspect (1)
339 {
340     // special case for desktop resolution: window size of 640x480
341     if ( r == ArmageTron_Desktop )
342     {
343         windowSize = rScreenSize( ArmageTron_640_480 );
344     }
345 }
346 
sr_ReinitDisplay()347 void sr_ReinitDisplay(){
348     sr_ExitDisplay();
349     if (!sr_InitDisplay()){
350         tERR_ERROR("Oops. Failed to reinit video hardware. "
351                    "Resetting to defaults..\n");
352         exit(-1);
353     }
354 
355 }
356 
357 
358 // *******************************************
359 
360 
361 
362 // GL information
363 
364 tString gl_vendor;
365 tString gl_renderer;
366 tString gl_version;
367 tString gl_extensions;
368 
369 bool software_renderer=false;
370 bool last_software_renderer=false;
371 
372 static tConfItem<bool> lsr("SOFTWARE_RENDERER",last_software_renderer);
373 
374 tString lastError("Unknown");
375 
376 #ifndef DEDICATED
countBits(unsigned int count)377 static int countBits(unsigned int count)
378 {
379     int ret = 0;
380     while (count)
381     {
382         ret    += count & 1;
383         count >>= 1;
384     }
385 
386     return ret;
387 }
388 #endif
389 
lowlevel_sr_InitDisplay()390 static bool lowlevel_sr_InitDisplay(){
391 #ifndef DEDICATED
392     rScreenSize & res = currentScreensetting.fullscreen ? currentScreensetting.res : currentScreensetting.windowSize;
393 
394     // update pixel aspect ratio
395     if ( res.res != ArmageTron_Invalid )
396         currentScreensetting.aspect = aspect[res.res];
397 
398 #ifndef DIRTY
399     currentScreensetting.useSDL = true;
400 #endif
401     res.UpdateSize();
402     sr_screenWidth = res.width;
403     sr_screenHeight= res.height;
404 
405     if (!sr_screen)
406     {
407         int singleCD_R	= 5;
408         int singleCD_G	= 5;
409         int singleCD_B	= 5;
410         int fullCD		= 16;
411         int zDepth		= 16;
412 
413         switch (currentScreensetting.colorDepth)
414         {
415         case ArmageTron_ColorDepth_16:
416             // parameters already set for this depth
417             break;
418         case ArmageTron_ColorDepth_Desktop:
419             {
420                 const SDL_VideoInfo* videoInfo     = SDL_GetVideoInfo( );
421                 const SDL_PixelFormat* pixelFormat = videoInfo->vfmt;
422                 fullCD         		               = pixelFormat->BitsPerPixel;
423                 singleCD_R                         = countBits(pixelFormat->Rmask);
424                 singleCD_G                         = countBits(pixelFormat->Gmask);
425                 singleCD_B                         = countBits(pixelFormat->Bmask);
426             }
427             break;
428         case ArmageTron_ColorDepth_32:
429             singleCD_R	= 8;
430             singleCD_G	= 8;
431             singleCD_B	= 8;
432             fullCD		= 24;
433             zDepth		= 32;
434             break;
435         }
436 
437         switch ( currentScreensetting.zDepth )
438         {
439         case ArmageTron_ColorDepth_16: zDepth = 16; break;
440         case ArmageTron_ColorDepth_32: zDepth = 32; break;
441         default: break;
442         }
443 
444 #ifdef SDL_OPENGL
445         if (currentScreensetting.useSDL)
446         {
447             // SDL 1.1 required
448             SDL_GL_SetAttribute( SDL_GL_RED_SIZE, singleCD_R );
449             SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, singleCD_G );
450             SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, singleCD_B );
451             SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, zDepth );
452             SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
453         }
454 #else
455         currentScreensetting.useSDL = false;
456 #endif
457 
458 
459 
460         /*
461           #ifdef POWERPAK_DEB
462           PD_SetGFXMode(sr_screenWidth, sr_screenHeight, 32, PD_DEFAULT);
463           sr_screen=DoubleBuffer;
464           #else
465         */
466 
467         int attrib;
468 
469 #ifdef SDL_OPENGL
470         if (currentScreensetting.useSDL)
471         {
472             // SDL 1.1
473 #ifndef FORCE_WINDOW
474             if (currentScreensetting.fullscreen)
475                 attrib=SDL_OPENGL | SDL_FULLSCREEN;
476             else
477 #endif
478                 attrib=SDL_OPENGL;
479         }
480         else
481 #endif
482         {
483 #ifndef FORCE_WINDOW
484             if (currentScreensetting.fullscreen)
485                 attrib=SDL_DOUBLEBUF | SDL_SWSURFACE | SDL_FULLSCREEN;
486             else
487 #endif
488                 attrib=SDL_DOUBLEBUF | SDL_SWSURFACE;
489         }
490 
491 #ifdef FORCE_WINDOW
492 #ifdef WIN32
493         //		sr_screenWidth  = 400;
494         //		sr_screenHeight = 300;
495 #else
496         //		sr_screenWidth  = 640;
497         //		sr_screenHeight = 480;
498 #endif
499 #endif
500         int CD = fullCD;
501 
502         // only check for errors if requested and if we're not about to set the
503         // desktop resolution, where SDL_VideoModeOK apparently doesn't work.
504         if (currentScreensetting.checkErrors && sr_screenWidth + sr_screenHeight > 0)
505         {
506             // check if the video mode should be OK:
507             CD = SDL_VideoModeOK
508                  (sr_screenWidth, sr_screenHeight,   fullCD,
509                   attrib);
510 
511             // if not quite right
512             if (CD < fullCD){
513                 // check if the other fs/windowed mode is better
514                 int CD_fsinv = SDL_VideoModeOK
515                                (sr_screenWidth, sr_screenHeight,   fullCD,
516                                 attrib^SDL_FULLSCREEN);
517 
518                 if (CD_fsinv > fullCD){
519                     // yes! change the mode
520                     currentScreensetting.fullscreen=!currentScreensetting.fullscreen;
521                     attrib ^= SDL_FULLSCREEN;
522                     CD = CD_fsinv;
523                 }
524             }
525 
526             if (CD < fullCD && currentScreensetting.colorDepth != ArmageTron_ColorDepth_16)
527             {
528                 currentScreensetting.colorDepth = ArmageTron_ColorDepth_16;
529 
530 #ifdef SDL_OPENGL
531                 if (currentScreensetting.useSDL)
532                 {
533                     // SDL 1.1 required
534                     SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
535                     SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
536                     SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
537                     SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
538                     SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
539                 }
540 #endif
541             }
542         }
543 
544         // determine desktop resolution
545         static int sr_desktopWidth = 0, sr_desktopHeight = 0;
546         if ( sr_desktopWidth == 0 && !sr_screen )
547         {
548             // select sane defaults in case the following operation fails
549             sr_desktopWidth = 640;
550             sr_desktopHeight = 480;
551 
552             if ( sr_DesktopScreensizeSupported()
553 #ifdef DEBUG
554                  && currentScreensetting.fullscreen && sr_screenWidth + sr_screenHeight == 0
555 #endif
556                 )
557             {
558                 sr_screen=SDL_SetVideoMode( 0, 0, CD, attrib );
559                 if ( sr_screen )
560                 {
561                     sr_desktopWidth = sr_screen->w;
562                     sr_desktopHeight = sr_screen->h;
563                 }
564             }
565         }
566 
567         // if desktop resolution was selected, pick it
568         if ( sr_screenWidth + sr_screenHeight == 0 )
569         {
570             sr_screenWidth = sr_desktopWidth;
571             sr_screenHeight = sr_desktopHeight;
572         }
573         else
574         {
575             // have the screen reinited
576             sr_screen = NULL;
577         }
578 
579         // only reinit the screen if the desktop res detection hasn't left us
580         // with a perfectly good one.
581         if ( !sr_screen && (sr_screen=SDL_SetVideoMode
582                         (sr_screenWidth, sr_screenHeight,   CD,
583                          attrib))
584                 == NULL)
585         {
586             if((sr_screen=SDL_SetVideoMode
587                           (sr_screenWidth, sr_screenHeight,    CD,
588                            attrib^SDL_FULLSCREEN))==NULL )
589             {
590                 lastError.Clear();
591                 lastError << "Couldn't set video mode: ";
592                 lastError << SDL_GetError();
593                 std::cerr << lastError << '\n';
594                 return false;
595             }
596             else
597             {
598                 currentScreensetting.fullscreen=!currentScreensetting.fullscreen;
599                 /*
600                 				// try again!
601                 				sr_ExitDisplay();
602 
603                 				if ( (sr_screen=SDL_SetVideoMode
604                 					  (sr_screenWidth, sr_screenHeight,   CD,
605                 					   attrib))
606                 					 == NULL)
607                 				{
608                 					if((sr_screen=SDL_SetVideoMode
609                 						(sr_screenWidth, sr_screenHeight,    CD,
610                 						 attrib^SDL_FULLSCREEN))==NULL )
611                 					{
612                 						lastError.Clear();
613                 						lastError << "Couldn't set video mode: ";
614                 						lastError << SDL_GetError();
615                 						std::cerr << lastError << '\n';
616                 						return false;
617                 					}
618                 					else
619                 						currentScreensetting.fullscreen=!currentScreensetting.fullscreen;
620                 				}
621                 */
622             }
623         }
624 
625         // MacOSX SDL 1.2.4 crashes if we SetCaption after switch to fullscreen. (fixed in 1.2.5)
626         if(!currentScreensetting.fullscreen)
627         {
628             tOutput o("Armagetron Advanced");
629             tString s;
630             s << o;
631             SDL_WM_SetCaption(s, s);
632         }
633 
634         SDL_EnableUNICODE(1);
635     }
636 
637 #ifdef DIRTY
638     if (!currentScreensetting.useSDL)
639         if(!rSysDep::InitGL()) return false;
640 #endif
641 
642 #ifndef DEDICATED
643     gl_vendor.SetLen(0);
644     gl_renderer.SetLen(0);
645     gl_version.SetLen(0);
646     gl_extensions.SetLen(0);
647     renderer_identification.SetLen(0);
648 
649     gl_vendor     << reinterpret_cast<const char *>(glGetString(GL_VENDOR));
650     gl_renderer   << reinterpret_cast<const char *>(glGetString(GL_RENDERER));
651     gl_version    << reinterpret_cast<const char *>(glGetString(GL_VERSION));
652     gl_extensions << reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
653 
654     // display list blacklist
655     sr_blacklistDisplayLists=false;
656 
657     if(strstr(gl_version,"Mesa 7.0") || strstr(gl_version,"Mesa 7.1"))
658     {
659         // mesa DRI and software has problems in the 7.0/7.1 series
660         sr_blacklistDisplayLists=true;
661     }
662 
663     if(strstr(gl_vendor,"SiS"))
664     {
665         // almost nobody has those cards/chips, and we have
666         // at least one bluescreen problem reported.
667         sr_blacklistDisplayLists=true;
668     }
669 
670 
671 #ifndef WIN32
672     if(!strstr(gl_renderer,"Voodoo3"))
673 #endif
674     {
675         if(currentScreensetting.fullscreen)
676             SDL_ShowCursor(0);
677         else
678             SDL_ShowCursor(1);
679     }
680 
681 #ifdef WIN32
682     renderer_identification << "WIN32 ";
683 #else
684 #ifdef MACOSX
685     renderer_identification << "MACOSX ";
686 #else
687     renderer_identification << "LINUX ";
688 #endif
689 #endif
690     renderer_identification << rRenderIdCallback::RenderId() << ' ';
691 #ifdef SDL_OPENGL
692     renderer_identification << "SDL 1.2\n";
693     renderer_identification << "USE_SDL=" << currentScreensetting.useSDL
694     << '\n';
695 #else
696     renderer_identification << "SDL 1.0\n";
697 #endif
698     renderer_identification << "CD=" << currentScreensetting.colorDepth  << '\n';
699     renderer_identification << "FS=" << currentScreensetting.fullscreen  << '\n';
700     renderer_identification << "GL_VENDOR=" << gl_vendor   << '\n';
701     renderer_identification << "GL_RENDERER=" << gl_renderer << '\n';
702     renderer_identification << "GL_VERSION=" << gl_version  << '\n';
703 #endif
704 
705     if (// test for Windows software GL (be a little flexible...)
706         (
707             strstr(gl_vendor,"icrosoft") || strstr(gl_vendor,"SGI")
708         )
709         && strstr(gl_renderer,"eneric")
710     )
711         software_renderer=true;
712 
713     if ( // test for Mesa software GL
714         strstr(gl_vendor,"rian") && strstr(gl_renderer,"X11") &&
715         strstr(gl_renderer,"esa")
716     )
717         software_renderer=true;
718 
719     if ( // test for Mesa software GL, new versions
720         strstr(gl_vendor,"Mesa") &&
721         strstr(gl_renderer,"Software Rasterizer")
722         )
723         software_renderer=true;
724 
725     if ( // test for GLX software GL
726         strstr(gl_renderer,"GLX") &&
727         strstr(gl_renderer,"ndirect") &&
728         strstr(gl_renderer,"esa")
729     )
730         software_renderer=true;
731 
732     // disable storage of non-alpha textures on Savage MX
733     if ( strstr( gl_renderer, "SavageMX" ) )
734     {
735         rISurfaceTexture::storageHack_ = true;
736     }
737 
738     // fonts look best in bilinear filtering, no mipmaps
739     if ( rTextureGroups::TextureMode[rTextureGroups::TEX_FONT] > GL_LINEAR )
740         rTextureGroups::TextureMode[rTextureGroups::TEX_FONT] = GL_LINEAR;
741 
742     // disable trilinear filtering for ATI cards
743     if ( strstr( gl_vendor, "ATI" ) )
744     {
745         default_texturemode = GL_LINEAR_MIPMAP_NEAREST;
746     }
747 
748     // wait for activation if we were ALT-Tabbed away:
749     while ( (SDL_GetAppState() & SDL_APPACTIVE) == 0)
750     {
751         SDL_Delay(100);
752         SDL_PumpEvents();
753     }
754 
755     if (software_renderer && !last_software_renderer)
756         sr_LoadDefaultConfig();
757 
758     last_software_renderer=software_renderer;
759 
760 
761     // wait for activation if we were ALT-Tabbed away:
762     while ( (SDL_GetAppState() & SDL_APPACTIVE) == 0)
763     {
764         SDL_Delay(100);
765         SDL_PumpEvents();
766     }
767 
768     sr_ResetRenderState(true);
769 
770     rCallbackAfterScreenModeChange::Exec();
771 #endif
772     return true;
773 }
774 
775 bool cycleprograminited = false;
776 
sr_InitDisplay()777 bool sr_InitDisplay(){
778     cycleprograminited = false;
779     while (failed_attempts <= MAXEMERGENCY+1)
780     {
781 #ifndef DEBUG
782         if (failed_attempts)
783             currentScreensetting = *emergency[failed_attempts];
784 
785         failed_attempts++;
786         st_SaveConfig();
787 
788         //      std::cout << failed_attempts << "\n";
789         //      std::cout.flush();
790 #endif
791 
792 #ifdef MACOSX
793         // init the screen once in windowed mode
794         static bool first = true;
795         if ( first && currentScreensetting.fullscreen )
796         {
797             first = false;
798             currentScreensetting.fullscreen = false;
799 
800             sr_LockSDL();
801             if (lowlevel_sr_InitDisplay())
802             {
803                 sr_ExitDisplay();
804             }
805             sr_UnlockSDL();
806 
807             currentScreensetting.fullscreen = true;
808         }
809 #endif
810 
811         sr_LockSDL();
812         if (lowlevel_sr_InitDisplay())
813         {
814             lastSuccess=currentScreensetting;
815             sr_UnlockSDL();
816             return true;
817         }
818 
819         st_SaveConfig();
820 
821         if (lowlevel_sr_InitDisplay())
822         {
823             lastSuccess=currentScreensetting;
824             sr_UnlockSDL();
825             return true;
826         }
827         sr_UnlockSDL();
828 
829 
830     }
831 
832     failed_attempts = 1;
833     st_SaveConfig();
834 
835     tERR_ERROR("\nSorry, played all my cards trying to "
836                "initialize your video system.\n"
837                << tOutput("$program_name") << " won't run on your computer. Reason:\n\n"
838                << lastError
839                << "\n\nI'll try again from the beginning, but the "
840                << "chances of success are minimal.\n"
841               );
842 
843     return false;
844 }
845 
846 
sr_ExitDisplay()847 void sr_ExitDisplay(){
848 #ifndef DEDICATED
849     rCallbackBeforeScreenModeChange::Exec();
850 
851 #ifdef DIRTY
852     rSysDep::ExitGL();
853 #endif
854 
855     if (sr_screen){
856         failed_attempts = 0;
857         st_SaveConfig();
858 
859         sr_LockSDL();
860         // z-man: according to man SDL_SetVideoSurface, screen should not bee freed.
861         // SDL_FreeSurface(sr_screen);
862         sr_screen=NULL;
863         sr_UnlockSDL();
864         //SDL_Quit();
865     }
866 #endif
867 }
868 
869 bool    sr_alphaBlend=true;
870 bool    sr_glOut=true;
871 bool    sr_smoothShading=true;
872 
873 
874 int sr_floorMirror=0;
875 int sr_floorDetail=rFLOOR_TEXTURE;
876 bool sr_highRim=true;
877 bool sr_upperSky=false;
878 bool sr_lowerSky=false;
879 bool sr_skyWobble=true;
880 bool sr_dither=true;
881 bool sr_infinityPlane=false;
882 bool sr_laggometer=true;
883 bool sr_predictObjects=false;
884 bool sr_texturesTruecolor=false;
885 
886 bool sr_textOut=false;
887 bool sr_FPSOut=true;
888 
889 bool sr_keepWindowActive=false;
890 
891 tString renderer_identification;
892 
sr_LoadDefaultConfig()893 void sr_LoadDefaultConfig(){
894 
895     // High detail defaults; no problem for your ordinary 3d-card.
896     sr_alphaBlend=true;
897     sr_useDisplayLists=rDisplayList_Off;
898     sr_textOut=true;
899     sr_dither=true;
900     sr_smoothShading=true;
901     int i;
902 #ifndef DEDICATED
903     for (i=rTextureGroups::TEX_GROUPS-1;i>=0;i--)
904         rTextureGroups::TextureMode[i]=default_texturemode;
905 
906     // fonts look best in bilinear filtering, no mipmaps
907     rTextureGroups::TextureMode[rTextureGroups::TEX_FONT]=GL_LINEAR;
908 #endif
909     sr_floorDetail=rFLOOR_TWOTEXTURE;
910     sr_floorMirror=rMIRROR_OFF;
911     sr_infinityPlane=false;
912     sr_lowerSky=false;
913     sr_upperSky=false;
914     sr_keepWindowActive=false;
915     rSysDep::swapMode_=rSysDep::rSwap_glFinish;
916 
917     if (software_renderer){
918         // A software renderer! Poor soul. Set low details:
919         for (i=rTextureGroups::TEX_GROUPS-1;i>=0;i--)
920             rTextureGroups::TextureMode[i]=-1;
921 
922 #ifndef DEDICATED
923         rTextureGroups::TextureMode[rTextureGroups::TEX_OBJ]=GL_NEAREST_MIPMAP_NEAREST;
924         rTextureGroups::TextureMode[rTextureGroups::TEX_FONT]=GL_NEAREST_MIPMAP_NEAREST;
925 #endif
926 
927         sr_highRim=false;
928         sr_dither=false;
929         sr_alphaBlend=false;
930         sr_smoothShading=true; // smooth shading does not slow down the
931         // two tested renderers; leave it it.
932         sr_floorDetail=rFLOOR_GRID;
933         sr_floorMirror=rMIRROR_OFF;
934     }
935     else if(strstr(gl_vendor,"3Dfx")){
936         //workaround for 3dfx renderer: aliasing must be turned on
937         //sr_lineAntialias=rFEAT_OFF;
938     }
939     else if(strstr(gl_vendor,"NVIDIA")){
940         // infinity , display lists and glFlush swapping work for NVIDIA
941         sr_infinityPlane=true;
942         sr_useDisplayLists=rDisplayList_CAC;
943         rSysDep::swapMode_=rSysDep::rSwap_glFlush;
944     }
945 #ifdef MACOSX
946     else if(strstr(gl_vendor,"ATI")){
947         // glFlush swapping work for ATI on the mac
948         rSysDep::swapMode_=rSysDep::rSwap_glFlush;
949     }
950 #endif
951     else if(strstr(gl_vendor,"Matrox")){
952         sr_floorDetail = rFLOOR_TEXTURE;  // double textured floor does not work
953     }
954 
955     /*
956     else if(strstr(gl_version,"Mesa"))
957     {
958         sr_useDisplayLists=rDisplayList_Off;
959     }
960     */
961 }
962 
sr_ResetRenderState(bool menu)963 void sr_ResetRenderState(bool menu){
964     if(!sr_glOut)
965         return;
966 #ifndef DEDICATED
967 
968     // Z-Buffering and perspective correction
969 
970     if (menu){
971         glDisable(GL_DEPTH_TEST);
972         glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
973         glViewport (0, 0, GLsizei(sr_screenWidth), GLsizei(sr_screenHeight));
974     }
975     else{
976         glEnable(GL_DEPTH_TEST);
977         glDepthFunc(GL_LEQUAL);
978     }
979 
980     if (sr_dither)
981         glEnable(GL_DITHER);
982     else
983         glDisable(GL_DITHER);
984 
985     glDisable(GL_LIGHTING);
986 
987     // disable texture mapping (selecting textures will reactivate it)
988 
989     //  glDisable(GL_TEXTURE);
990     glDisable(GL_TEXTURE_2D);
991 
992 
993     // flat or smooth shading
994     if (sr_smoothShading)
995         glShadeModel(GL_SMOOTH);
996     else
997         glShadeModel(GL_FLAT);
998 
999     // alpha blending
1000     if (sr_alphaBlend){
1001         glEnable(GL_ALPHA_TEST);
1002         glAlphaFunc(GL_GREATER,0);
1003         glEnable(GL_BLEND);
1004         glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
1005     }
1006     else{
1007         glDisable(GL_ALPHA_TEST);
1008         glDisable(GL_BLEND);
1009     }
1010 
1011     // reset matrices
1012     glMatrixMode(GL_TEXTURE);
1013     glLoadIdentity();
1014 
1015     glMatrixMode(GL_PROJECTION);
1016     glLoadIdentity();
1017 
1018     glMatrixMode(GL_MODELVIEW);
1019     glLoadIdentity();
1020 #endif
1021 }
1022 
1023 
1024 /*
1025 static uMenuItemFunction apply
1026 (&sg_screenMenu_mode,"Apply Changes",
1027 "This activates the changes to the resolution and fullscreen/windowed mode "
1028 "made above. This does not work on all systems; exit and reenter Armagetron "
1029 "instead if you experience problems.",
1030  sr_ReinitDisplay);
1031 */
1032 
1033 
1034 
1035 
1036 
1037 //static bool offs=false;
1038 
sr_DepthOffset(bool offset)1039 void sr_DepthOffset(bool offset){
1040     // return;
1041     //  if(offset!=offs){
1042     //offs=offset;
1043 #ifndef DEDICATED
1044     if (offset){
1045         //glMatrixMode(GL_PROJECTION);
1046         //glScalef(.9,.9,.9);
1047         glPolygonOffset(-2,-5);
1048         glEnable(GL_POLYGON_OFFSET_LINE);
1049         glEnable(GL_POLYGON_OFFSET_POINT);
1050         glEnable(GL_POLYGON_OFFSET_FILL);
1051     }
1052     else{
1053         glPolygonOffset(0,0);
1054         glDisable(GL_POLYGON_OFFSET_POINT);
1055         glDisable(GL_POLYGON_OFFSET_LINE);
1056         glDisable(GL_POLYGON_OFFSET_FILL);
1057         //glMatrixMode(GL_PROJECTION);
1058         //glScalef(1/.9,1/.9,1/.9);
1059     }
1060     //  }
1061 #endif
1062 }
1063 
1064 // set activation staus
sr_Activate(bool active)1065 void sr_Activate(bool active)
1066 {
1067 #ifndef DEDICATED
1068     if ( !currentScreensetting.fullscreen && !active && sr_keepWindowActive )
1069     {
1070         sr_glOut=!active;
1071     }
1072     else
1073     {
1074         sr_glOut=active;
1075     }
1076 
1077     // unload textures and stuff if rendering gets disabled
1078     if (!sr_glOut)
1079         rCallbackBeforeScreenModeChange::Exec();
1080 
1081     // Jonathans fullscreen bugfix.
1082     // z-man's ammendmend: apparently, doing this in Linux is painful as well.
1083     // Only on Windows, you get a deactivation event when you ALT-TAB away
1084     // from th application, then iconification is the right thing to do.
1085     // On Linux at least, there is no standard alt-tab for fullscreen applications.
1086 #ifdef WIN32
1087     if ( currentScreensetting.fullscreen && !active )
1088     {
1089         SDL_WM_IconifyWindow();
1090     }
1091 #endif
1092 #endif
1093 }
1094 
1095 //**************************************
1096 //** Screen mode callbacks            **
1097 //**************************************
1098 
1099 
1100 static tCallback *sr_BeforeAnchor;
1101 
rCallbackBeforeScreenModeChange(VOIDFUNC * f)1102 rCallbackBeforeScreenModeChange::rCallbackBeforeScreenModeChange(VOIDFUNC *f)
1103         :tCallback(sr_BeforeAnchor, f){}
1104 
Exec()1105 void rCallbackBeforeScreenModeChange::Exec()
1106 {
1107     tCallback::Exec(sr_BeforeAnchor);
1108 }
1109 
1110 static tCallback *sr_AfterAnchor;
1111 
rCallbackAfterScreenModeChange(VOIDFUNC * f)1112 rCallbackAfterScreenModeChange::rCallbackAfterScreenModeChange(VOIDFUNC *f)
1113         :tCallback(sr_AfterAnchor, f){}
1114 
Exec()1115 void rCallbackAfterScreenModeChange::Exec()
1116 {
1117     tCallback::Exec(sr_AfterAnchor);
1118 }
1119 
1120