00001 /* 00002 00003 ************************************************************************* 00004 00005 ArmageTron -- Just another Tron Lightcycle Game in 3D. 00006 Copyright (C) 2008 Manuel Moos (manuel@moosnet.de) and the AA Development Team 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00023 00024 *************************************************************************** 00025 00026 */ 00027 00028 #include "rDisplayList.h" 00029 00030 #include "rScreen.h" 00031 00032 #ifdef DEBUG 00033 #define LIST_STATS 00034 #endif 00035 00036 #ifdef LIST_STATS 00037 class rListCounter 00038 { 00039 public: 00040 enum Type 00041 { 00042 Use, // display list used 00043 Create, // created 00044 Not, // not used 00045 COUNT 00046 }; 00047 00048 rListCounter(){ count_[Use] = count_[Create] = count_[Not] = 0; } 00049 void Count( Type type ) 00050 { 00051 count_[type]++; 00052 } 00053 ~rListCounter() 00054 { 00055 std::cout << "Display Lists Created: " << count_[Create] << ", used: " << count_[Use] 00056 << " and passed: " << count_[Not] << ".\n"; 00057 } 00058 private: 00059 unsigned int count_[COUNT]; 00060 }; 00061 00062 static rListCounter sr_counter; 00063 #endif 00064 00065 #ifndef DEDICATED 00066 static rDisplayList * se_displayListAnchor = NULL; 00067 #endif 00068 00069 rDisplayList::rDisplayList() 00070 #ifndef DEDICATED 00071 : tListItem< rDisplayList >( se_displayListAnchor ) 00072 , list_( 0 ) 00073 , inhibit_( 0 ) 00074 , filling_( false ) 00075 #endif 00076 { 00077 } 00078 00079 rDisplayList::~rDisplayList() 00080 { 00081 #ifndef DEDICATED 00082 tASSERT( !filling_ ); 00083 00084 Clear(); 00085 00086 tASSERT( !list_ ); 00087 #endif 00088 } 00089 00090 static rDisplayListFiller * sr_currentFiller = NULL; 00091 00093 bool rDisplayList::IsRecording() 00094 { 00095 return sr_currentFiller; 00096 } 00097 00098 // calls the display list, returns true if there was a list to call 00099 bool rDisplayList::OnCall() 00100 { 00101 #ifndef DEDICATED 00102 tASSERT( !filling_ ); 00103 00104 // no playback while another list is recorded; this 00105 // gives us a chance to agglomerate primitives. 00106 if ( IsRecording() ) 00107 { 00108 return false; 00109 } 00110 00111 if ( inhibit_ > 0 && list_ ) 00112 { 00113 Clear(); 00114 --inhibit_; 00115 return false; 00116 } 00117 00118 if ( list_ ) 00119 { 00120 #ifdef LIST_STATS 00121 sr_counter.Count( rListCounter::Use ); 00122 #endif 00123 glCallList( list_ ); 00124 return true; 00125 } 00126 #endif 00127 00128 return false; 00129 } 00130 00132 void rDisplayList::Clear( int inhibitGeneration ) 00133 { 00134 #ifndef DEDICATED 00135 00136 // clear the list 00137 if ( !filling_ && list_ ) 00138 { 00139 glDeleteLists( list_, 1 ); 00140 list_ = 0; 00141 } 00142 else 00143 { 00144 // clear it later 00145 if ( list_ && inhibitGeneration < 1 ) 00146 { 00147 inhibitGeneration = 1; 00148 } 00149 } 00150 00151 // memorize inhibit counter 00152 if ( inhibit_ < inhibitGeneration ) 00153 { 00154 inhibit_ = inhibitGeneration; 00155 } 00156 #endif 00157 } 00158 00159 // clears all display lists 00160 void rDisplayList::ClearAll() 00161 { 00162 #ifndef DEDICATED 00163 tASSERT(!IsRecording()); 00164 00165 rDisplayList *run = se_displayListAnchor; 00166 while (run) 00167 { 00168 run->Clear(); 00169 run = run->Next(); 00170 } 00171 #endif 00172 } 00173 00174 // cancels recording of current display list 00175 void rDisplayList::Cancel() 00176 { 00177 #ifndef DEDICATED 00178 if ( sr_currentFiller ) 00179 { 00180 sr_currentFiller->list_.Clear(0); 00181 sr_currentFiller->Stop(); 00182 } 00183 #endif 00184 } 00185 00186 rDisplayListAlphaSensitive::rDisplayListAlphaSensitive() 00187 : lastAlpha_( sr_alphaBlend ) 00188 {} 00189 00190 bool rDisplayListAlphaSensitive::OnCall() 00191 { 00192 // check whether crucial settings changed 00193 if ( sr_alphaBlend != lastAlpha_ ) 00194 { 00195 lastAlpha_ = sr_alphaBlend; 00196 return false; 00197 } 00198 00199 return rDisplayList::OnCall(); 00200 } 00201 00203 rDisplayListFiller::rDisplayListFiller( rDisplayList & list ) 00204 #ifndef DEDICATED 00205 : list_( list ) 00206 #endif 00207 { 00208 Start(); 00209 } 00210 00211 // starts filling the display list 00212 void rDisplayListFiller::Start() 00213 { 00214 #ifndef DEDICATED 00215 bool useList = sr_useDisplayLists != rDisplayList_Off && list_.inhibit_ == 0 && !sr_currentFiller; 00216 if ( useList ) 00217 { 00218 #ifdef LIST_STATS 00219 sr_counter.Count( rListCounter::Create ); 00220 #endif 00221 if ( !list_.list_ ) 00222 { 00223 list_.list_=glGenLists(1); 00224 tASSERT( list_.list_ ); 00225 } 00226 glNewList(list_.list_, sr_useDisplayLists == rDisplayList_CAC ? GL_COMPILE : GL_COMPILE_AND_EXECUTE ); 00227 list_.filling_ = true; 00228 sr_currentFiller = this; 00229 } 00230 else if ( list_.inhibit_ > 0 ) 00231 { 00232 --list_.inhibit_; 00233 } 00234 00235 #ifdef LIST_STATS 00236 if ( !useList && !sr_currentFiller ) 00237 { 00238 sr_counter.Count( rListCounter::Not ); 00239 } 00240 #endif 00241 #endif 00242 } 00243 00244 rDisplayListFiller::~rDisplayListFiller() 00245 { 00246 Stop(); 00247 } 00248 00250 void rDisplayListFiller::Stop() 00251 { 00252 #ifndef DEDICATED 00253 if ( list_.filling_ ) 00254 { 00255 tASSERT( list_.list_ ); 00256 tASSERT( sr_currentFiller == this ); 00257 00258 sr_currentFiller = 0; 00259 list_.filling_ = false; 00260 glEndList(); 00261 00262 if ( sr_useDisplayLists == rDisplayList_CAC ) 00263 { 00264 // call the list, making sure it really gets executed 00265 int inhibit = list_.inhibit_; 00266 list_.inhibit_ = 0; 00267 list_.Call(); 00268 list_.inhibit_ = inhibit; 00269 } 00270 } 00271 00272 // to debug, clearing every display list may be useful: 00273 // list_.Clear(0); 00274 #endif 00275 } 00276 00277 static rCallbackBeforeScreenModeChange sr_unload( &rDisplayList::ClearAll );