# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

vegetablevb_allocator.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "std3d.h"
00027 
00028 
00029 #include "3d/vegetablevb_allocator.h"
00030 #include "3d/vegetable_def.h"
00031 
00032 
00033 using namespace std;
00034 using namespace NLMISC;
00035 
00036 namespace NL3D 
00037 {
00038 
00039 
00040 /*
00041         Once a reallocation of a VBHard occurs, how many vertices we add to the re-allocation, to avoid 
00042         as possible reallocations.
00043 */
00044 #define NL3D_VEGETABLE_VERTEX_ALLOCATE_SECURITY         1024
00045 /*
00046         The start size of the array.
00047 */
00048 #define NL3D_VEGETABLE_VERTEX_ALLOCATE_START            4048
00049 
00050 
00051 #define NL3D_VEGETABLE_VERTEX_FREE_MEMORY_RESERVE       1024
00052 
00053 
00054 // ***************************************************************************
00055 CVegetableVBAllocator::CVegetableVBAllocator()
00056 {
00057         _Type= VBTypeUnlit;
00058         _MaxVertexInBufferHard= 0;
00059 
00060         // Init free list
00061         _VertexFreeMemory.reserve(NL3D_VEGETABLE_VERTEX_FREE_MEMORY_RESERVE);
00062         _NumVerticesAllocated= 0;
00063 
00064         // Init vbhard
00065         _VBHardOk= false;
00066         _BufferLocked= false;
00067         _AGPBufferPtr= NULL;
00068 }
00069 
00070 
00071 // ***************************************************************************
00072 void                    CVegetableVBAllocator::init(TVBType type, uint maxVertexInBufferHard)
00073 {
00074         _Type= type;
00075         _MaxVertexInBufferHard= maxVertexInBufferHard;
00076 
00077         // According to _Type, build VB format, and create VertexProgram
00078         setupVBFormat();
00079 }
00080 
00081 
00082 // ***************************************************************************
00083 CVegetableVBAllocator::~CVegetableVBAllocator()
00084 {
00085         clear();
00086 }
00087 
00088 // ***************************************************************************
00089 void                    CVegetableVBAllocator::updateDriver(IDriver *driver)
00090 {
00091         // test change of driver.
00092         nlassert(driver && !_BufferLocked);
00093         // If change of driver
00094         if( _Driver==NULL || driver!=_Driver )
00095         {
00096                 // delete old VBHard.
00097                 deleteVertexBufferHard();
00098                 _Driver= driver;
00099                 _VBHardOk= (_MaxVertexInBufferHard>0) && (_Driver->supportVertexBufferHard());
00100 
00101                 // Driver must support VP.
00102                 nlassert(_Driver->isVertexProgramSupported());
00103 
00104                 // must reallocate the VertexBuffer.
00105                 if( _NumVerticesAllocated>0 )
00106                         allocateVertexBufferAndFillVBHard(_NumVerticesAllocated);
00107         }
00108         else
00109         {
00110                 // if VBHard possible, and if vbHardDeleted but space needed, reallocate.
00111                 if( _VBHardOk && _VBHard==NULL && _NumVerticesAllocated>0 )
00112                         allocateVertexBufferAndFillVBHard(_NumVerticesAllocated);
00113         }
00114 
00115 }
00116 
00117 // ***************************************************************************
00118 void                    CVegetableVBAllocator::clear()
00119 {
00120         // clear list.
00121         _VertexFreeMemory.clear();
00122         _NumVerticesAllocated= 0;
00123 
00124         // delete the VB.
00125         deleteVertexBufferHard();
00126         // really delete the VB soft too
00127         _VB.deleteAllVertices();
00128 
00129         // clear other states.
00130         _Driver= NULL;
00131         _VBHardOk= false;
00132 }
00133 
00134 
00135 // ***************************************************************************
00136 void                    CVegetableVBAllocator::lockBuffer()
00137 {
00138         // force unlock
00139         unlockBuffer();
00140 
00141         if(_VBHard)
00142         {
00143                 _AGPBufferPtr= (uint8*)_VBHard->lock();
00144         }
00145 
00146         _BufferLocked= true;
00147 }
00148 
00149 // ***************************************************************************
00150 void                    CVegetableVBAllocator::unlockBuffer()
00151 {
00152         if(_BufferLocked)
00153         {
00154                 if(_VBHard)
00155                         _VBHard->unlock();
00156                 _BufferLocked= false;
00157                 _AGPBufferPtr= NULL;
00158         }
00159 }
00160 
00161 
00162 // ***************************************************************************
00163 uint                    CVegetableVBAllocator::getNumUserVerticesAllocated() const
00164 {
00165         // get the number of vertices which are allocated by allocateVertex().
00166         return _NumVerticesAllocated - _VertexFreeMemory.size();
00167 }
00168 
00169 // ***************************************************************************
00170 bool                    CVegetableVBAllocator::exceedMaxVertexInBufferHard(uint numAddVerts) const
00171 {
00172         return (getNumUserVerticesAllocated() + numAddVerts) > _MaxVertexInBufferHard;
00173 }
00174 
00175 
00176 // ***************************************************************************
00177 uint                    CVegetableVBAllocator::allocateVertex()
00178 {
00179         // if no more free, allocate.
00180         if( _VertexFreeMemory.size()==0 )
00181         {
00182                 // enlarge capacity.
00183                 uint    newResize;
00184                 if(_NumVerticesAllocated==0)
00185                         newResize= NL3D_VEGETABLE_VERTEX_ALLOCATE_START;
00186                 else
00187                         newResize= NL3D_VEGETABLE_VERTEX_ALLOCATE_SECURITY;
00188                 // try to not overlap _MaxVertexInBufferHard limit, to avoid VBufferHard to be disabled.
00189                 if(_NumVerticesAllocated<_MaxVertexInBufferHard && _NumVerticesAllocated+newResize > _MaxVertexInBufferHard)
00190                 {
00191                         newResize= _MaxVertexInBufferHard - _NumVerticesAllocated;
00192                 }
00193                 _NumVerticesAllocated+= newResize;
00194                 // re-allocate VB.
00195                 allocateVertexBufferAndFillVBHard(_NumVerticesAllocated);
00196                 // resize infos on vertices.
00197                 _VertexInfos.resize(_NumVerticesAllocated);
00198 
00199                 // Fill list of free elements.
00200                 for(uint i=0;i<newResize;i++)
00201                 {
00202                         // create a new entry which points to this vertex.
00203                         // the list is made so allocation is in growing order.
00204                         _VertexFreeMemory.push_back( _NumVerticesAllocated - (i+1) );
00205 
00206                         // Mark as free the new vertices. (Debug).
00207                         _VertexInfos[_NumVerticesAllocated - (i+1)].Free= true;
00208                 }
00209         }
00210 
00211         // get a vertex (pop_back).
00212         uint    id= _VertexFreeMemory.back();
00213         // delete this vertex free entry.
00214         _VertexFreeMemory.pop_back();
00215 
00216         // check and Mark as not free the vertex. (Debug).
00217         nlassert(id<_NumVerticesAllocated);
00218         nlassert(_VertexInfos[id].Free);
00219         _VertexInfos[id].Free= false;
00220 
00221 
00222         return id;
00223 }
00224 
00225 // ***************************************************************************
00226 void                    CVegetableVBAllocator::deleteVertex(uint vid)
00227 {
00228         // check and Mark as free the vertex. (Debug).
00229         nlassert(vid<_NumVerticesAllocated);
00230         nlassert(!_VertexInfos[vid].Free);
00231         _VertexInfos[vid].Free= true;
00232 
00233         // Add this vertex to the free list.
00234         // create a new entry which points to this vertex.
00235         _VertexFreeMemory.push_back( vid );
00236 }
00237 
00238 // ***************************************************************************
00239 void                    *CVegetableVBAllocator::getVertexPointer(uint i)
00240 {
00241         return _VB.getVertexCoordPointer(i);
00242 }
00243 
00244 // ***************************************************************************
00245 void                    CVegetableVBAllocator::flushVertex(uint i)
00246 {
00247         if(_VBHardOk)
00248         {
00249                 nlassert(_VBHard && _BufferLocked);
00250                 // copy the VB soft to the VBHard.
00251                 void    *src= getVertexPointer(i);
00252                 void    *dst= _AGPBufferPtr + i*_VB.getVertexSize();
00253                 memcpy(dst, src, _VB.getVertexSize());
00254         }
00255 }
00256 
00257 // ***************************************************************************
00258 void                    CVegetableVBAllocator::activate()
00259 {
00260         nlassert(_Driver);
00261         nlassert(!_BufferLocked);
00262 
00263         // Activate VB.
00264         if(_VBHard)
00265                 _Driver->activeVertexBufferHard(_VBHard);
00266         else
00267                 _Driver->activeVertexBuffer(_VB);
00268 }
00269 
00270 
00271 // ***************************************************************************
00272 // ***************************************************************************
00273 // Vertex Buffer hard.
00274 // ***************************************************************************
00275 // ***************************************************************************
00276 
00277 
00278 // ***************************************************************************
00279 void                            CVegetableVBAllocator::deleteVertexBufferHard()
00280 {
00281         // must unlock VBhard before.
00282         unlockBuffer();
00283 
00284         // test (refptr) if the object still exist in memory.
00285         if(_VBHard!=NULL)
00286         {
00287                 // A vbufferhard should still exist only if driver still exist.
00288                 nlassert(_Driver!=NULL);
00289 
00290                 // delete it from driver.
00291                 _Driver->deleteVertexBufferHard(_VBHard);
00292                 _VBHard= NULL;
00293         }
00294 
00295 }
00296 
00297 // ***************************************************************************
00298 void                            CVegetableVBAllocator::allocateVertexBufferAndFillVBHard(uint32 numVertices)
00299 {
00300         // resize the Soft VB.
00301         _VB.setNumVertices(numVertices);
00302 
00303         // no allocation must be done if the Driver is not setuped, or if the driver has been deleted by refPtr.
00304         nlassert(_Driver);
00305 
00306         // must unlock VBhard before.
00307         bool    wasLocked= bufferLocked();
00308         unlockBuffer();
00309 
00310         // try to allocate a vbufferhard if possible.
00311         if( _VBHardOk )
00312         {
00313                 // delete possible old _VBHard.
00314                 if(_VBHard!=NULL)
00315                 {
00316                         // VertexBufferHard lifetime < Driver lifetime.
00317                         nlassert(_Driver!=NULL);
00318                         _Driver->deleteVertexBufferHard(_VBHard);
00319                 }
00320 
00321                 // try to create new one, in AGP Ram
00322                 // If too many vertices wanted, abort VBHard.
00323                 if(numVertices <= _MaxVertexInBufferHard)
00324                         _VBHard= _Driver->createVertexBufferHard(_VB.getVertexFormat(), _VB.getValueTypePointer(), numVertices, IDriver::VBHardAGP);
00325                 else
00326                         _VBHard= NULL;
00327 
00328                 // If KO, never try again.
00329                 if(_VBHard==NULL)
00330                         _VBHardOk= false;
00331                 else
00332                 {
00333                         // else, fill this AGP VBuffer Hard.
00334                         // lock before the AGP buffer
00335                         lockBuffer();
00336 
00337                         // copy all the vertices to AGP.
00338                         memcpy(_AGPBufferPtr, _VB.getVertexCoordPointer(0), _VB.getVertexSize() * numVertices);
00339 
00340                         // If was not locked before, unlock this VB
00341                         if(!wasLocked)
00342                                 unlockBuffer();
00343                 }
00344         }
00345 
00346         //nlinfo("VEGET: Alloc %d verts. %s", numVertices, _VBHardOk?"VBHard":"VBSoft");
00347 }
00348 
00349 
00350 // ***************************************************************************
00351 void                            CVegetableVBAllocator::setupVBFormat()
00352 {
00353         // Build the Vertex Format.
00354         _VB.clearValueEx();
00355 
00356         // if lighted, need world space normal and AmbientColor for each vertex.
00357         if( _Type == VBTypeLighted )
00358         {
00359                 _VB.addValueEx(NL3D_VEGETABLE_VPPOS_POS,        CVertexBuffer::Float3);         // v[0]
00360                 _VB.addValueEx(NL3D_VEGETABLE_VPPOS_NORMAL, CVertexBuffer::Float3);             // v[2]
00361                 _VB.addValueEx(NL3D_VEGETABLE_VPPOS_BENDINFO,   CVertexBuffer::Float3);         // v[9]
00362         }
00363         // If unlit
00364         else
00365         {
00366                 // slightly different VertexProgram, v[0].w== BendWeight, and v[9].x== v[0].norm()
00367                 _VB.addValueEx(NL3D_VEGETABLE_VPPOS_POS,                CVertexBuffer::Float4);         // v[0]
00368                 // Unlit VP has BlendDistance in v[9].w
00369                 _VB.addValueEx(NL3D_VEGETABLE_VPPOS_BENDINFO,   CVertexBuffer::Float4);         // v[9]
00370         }
00371         _VB.addValueEx(NL3D_VEGETABLE_VPPOS_COLOR0,             CVertexBuffer::UChar4);         // v[3]
00372         _VB.addValueEx(NL3D_VEGETABLE_VPPOS_COLOR1,             CVertexBuffer::UChar4);         // v[4]
00373         _VB.addValueEx(NL3D_VEGETABLE_VPPOS_TEX0,               CVertexBuffer::Float2);         // v[8]
00374         _VB.addValueEx(NL3D_VEGETABLE_VPPOS_CENTER,             CVertexBuffer::Float3);         // v[10]
00375         _VB.initEx();
00376 
00377 }
00378 
00379 
00380 
00381 } // NL3D