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