src/render/rDisplayList.cpp

Go to the documentation of this file.
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 );

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