vegetablevb_allocator.cpp
Go to the documentation of this file.00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "std3d.h"
00025
00026
00027 #include "nel/3d/vegetablevb_allocator.h"
00028 #include "nel/3d/vegetable_def.h"
00029
00030
00031 using namespace std;
00032 using namespace NLMISC;
00033
00034 namespace NL3D
00035 {
00036
00037
00038
00039
00040
00041
00042 #define NL3D_VEGETABLE_VERTEX_ALLOCATE_SECURITY 1024
00043
00044
00045
00046 #define NL3D_VEGETABLE_VERTEX_ALLOCATE_START 4048
00047
00048
00049 #define NL3D_VEGETABLE_VERTEX_FREE_MEMORY_RESERVE 1024
00050
00051
00052
00053 CVegetableVBAllocator::CVegetableVBAllocator()
00054 {
00055 _Type= VBTypeUnlit;
00056 _MaxVertexInBufferHard= 0;
00057
00058
00059 _VertexFreeMemory.reserve(NL3D_VEGETABLE_VERTEX_FREE_MEMORY_RESERVE);
00060 _NumVerticesAllocated= 0;
00061
00062
00063 _VBHardOk= false;
00064 _AGPBufferPtr= NULL;
00065 _RAMBufferPtr= NULL;
00066 }
00067
00068
00069
00070 void CVegetableVBAllocator::init(TVBType type, uint maxVertexInBufferHard)
00071 {
00072 _Type= type;
00073 _MaxVertexInBufferHard= maxVertexInBufferHard;
00074
00075
00076 setupVBFormat();
00077 }
00078
00079
00080
00081 CVegetableVBAllocator::~CVegetableVBAllocator()
00082 {
00083 clear();
00084 }
00085
00086
00087 void CVegetableVBAllocator::updateDriver(IDriver *driver)
00088 {
00089
00090 nlassert(driver && !_VBHard.isLocked());
00091
00092 if( _Driver==NULL || driver!=_Driver || (!_VBHard.isResident() && (_VBHard.capacity()!=0)))
00093 {
00094
00095 deleteVertexBufferHard();
00096 _Driver= driver;
00097 _VBHardOk= (_MaxVertexInBufferHard>0) && (_Driver->supportVertexBufferHard());
00098
00099
00100
00101
00102
00103
00104 if(_Driver->slowUnlockVertexBufferHard())
00105 _VBHardOk= false;
00106
00107
00108 nlassert(_Driver->isVertexProgramSupported());
00109
00110
00111 if( _NumVerticesAllocated>0 )
00112 allocateVertexBufferAndFillVBHard(_NumVerticesAllocated);
00113 }
00114 else
00115 {
00116
00117 if( _VBHardOk && _VBHard.getNumVertices()==0 && _NumVerticesAllocated>0 )
00118 allocateVertexBufferAndFillVBHard(_NumVerticesAllocated);
00119 }
00120
00121 }
00122
00123
00124 void CVegetableVBAllocator::clear()
00125 {
00126
00127 _VertexFreeMemory.clear();
00128 _NumVerticesAllocated= 0;
00129
00130
00131 unlockBuffer();
00132
00133
00134 deleteVertexBufferHard();
00135
00136 _VBSoft.deleteAllVertices();
00137
00138
00139 _Driver= NULL;
00140 _VBHardOk= false;
00141 }
00142
00143
00144
00145 void CVegetableVBAllocator::lockBuffer()
00146 {
00147
00148 unlockBuffer();
00149
00150
00151 if(_VBHardOk)
00152 {
00153
00154 _VBHard.lock(_VBAHard);
00155 _AGPBufferPtr=(uint8*)_VBAHard.getVertexCoordPointer();
00156
00157
00158 _VBSoft.lock(_VBASoft);
00159 _RAMBufferPtr=(const uint8*)_VBASoft.getVertexCoordPointer();
00160 }
00161 }
00162
00163
00164 void CVegetableVBAllocator::unlockBuffer()
00165 {
00166
00167 _VBAHard.unlock();
00168 _AGPBufferPtr= NULL;
00169
00170
00171 _VBASoft.unlock();
00172 _RAMBufferPtr= NULL;
00173 }
00174
00175
00176
00177 uint CVegetableVBAllocator::getNumUserVerticesAllocated() const
00178 {
00179
00180 return _NumVerticesAllocated - _VertexFreeMemory.size();
00181 }
00182
00183
00184 bool CVegetableVBAllocator::exceedMaxVertexInBufferHard(uint numAddVerts) const
00185 {
00186 return (getNumUserVerticesAllocated() + numAddVerts) > _MaxVertexInBufferHard;
00187 }
00188
00189
00190
00191 uint CVegetableVBAllocator::allocateVertex()
00192 {
00193
00194 if( _VertexFreeMemory.size()==0 )
00195 {
00196
00197 uint newResize;
00198 if(_NumVerticesAllocated==0)
00199 newResize= NL3D_VEGETABLE_VERTEX_ALLOCATE_START;
00200 else
00201 newResize= NL3D_VEGETABLE_VERTEX_ALLOCATE_SECURITY;
00202
00203 if(_NumVerticesAllocated<_MaxVertexInBufferHard && _NumVerticesAllocated+newResize > _MaxVertexInBufferHard)
00204 {
00205 newResize= _MaxVertexInBufferHard - _NumVerticesAllocated;
00206 }
00207 _NumVerticesAllocated+= newResize;
00208
00209 allocateVertexBufferAndFillVBHard(_NumVerticesAllocated);
00210
00211 _VertexInfos.resize(_NumVerticesAllocated);
00212
00213
00214 for(uint i=0;i<newResize;i++)
00215 {
00216
00217
00218 _VertexFreeMemory.push_back( _NumVerticesAllocated - (i+1) );
00219
00220
00221 _VertexInfos[_NumVerticesAllocated - (i+1)].Free= true;
00222 }
00223 }
00224
00225
00226 uint id= _VertexFreeMemory.back();
00227
00228 _VertexFreeMemory.pop_back();
00229
00230
00231 nlassert(id<_NumVerticesAllocated);
00232 nlassert(_VertexInfos[id].Free);
00233 _VertexInfos[id].Free= false;
00234
00235
00236 return id;
00237 }
00238
00239
00240 void CVegetableVBAllocator::deleteVertex(uint vid)
00241 {
00242
00243 nlassert(vid<_NumVerticesAllocated);
00244 nlassert(!_VertexInfos[vid].Free);
00245 _VertexInfos[vid].Free= true;
00246
00247
00248
00249 _VertexFreeMemory.push_back( vid );
00250 }
00251
00252
00253 void CVegetableVBAllocator::flushVertex(uint i)
00254 {
00255 if(_VBHardOk)
00256 {
00257 nlassert(_VBHard.getNumVertices() && _VBHard.isLocked() && _VBSoft.isLocked());
00258
00259
00260 uint size= _VBSoft.getVertexSize();
00261 const void *src= _RAMBufferPtr + i*size;
00262 void *dst= _AGPBufferPtr + i*size;
00263 CHECK_VBA_RANGE(_VBAHard, (uint8 *) dst, size);
00264 CHECK_VBA_RANGE(_VBASoft, (uint8 *) src, size);
00265 memcpy(dst, src, size);
00266 }
00267 }
00268
00269
00270 void CVegetableVBAllocator::activate()
00271 {
00272 nlassert(_Driver);
00273 nlassert(!_VBHard.isLocked());
00274 nlassert(!_VBSoft.isLocked());
00275
00276
00277 if(_VBHard.getNumVertices())
00278 _Driver->activeVertexBuffer(_VBHard);
00279 else
00280 _Driver->activeVertexBuffer(_VBSoft);
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 void CVegetableVBAllocator::deleteVertexBufferHard()
00293 {
00294
00295 unlockBuffer();
00296
00297
00298 if(_VBHard.getNumVertices()!=0)
00299 {
00300
00301 nlassert(_Driver!=NULL);
00302
00303
00304 _VBHard.deleteAllVertices ();
00305 }
00306
00307 }
00308
00309
00310 void CVegetableVBAllocator::allocateVertexBufferAndFillVBHard(uint32 numVertices)
00311 {
00312
00313 nlassert(_Driver);
00314
00315
00316 bool wasLocked= bufferLocked();
00317 unlockBuffer();
00318
00319
00320 _VBSoft.setNumVertices(numVertices);
00321
00322
00323 if( _VBHardOk )
00324 {
00325
00326
00327
00328
00329
00330
00331 if(_VBHard.getNumVertices() != _MaxVertexInBufferHard)
00332 {
00333
00334 if(_VBHard.getNumVertices()!=0)
00335 {
00336
00337 nlassert(_Driver!=NULL);
00338 _VBHard.deleteAllVertices();
00339 }
00340
00341
00342
00343 if(numVertices <= _MaxVertexInBufferHard)
00344 {
00345 _VBHard = _VBSoft;
00346 _VBHard.setPreferredMemory(CVertexBuffer::AGPPreferred, false);
00347 _VBHard.setNumVertices (_MaxVertexInBufferHard);
00348
00349
00350 nlverify (_Driver->activeVertexBuffer (_VBHard));
00351 nlassert (_VBHard.isResident());
00352
00353
00354 if (_VBHard.getLocation() == CVertexBuffer::RAMResident)
00355 _VBHard.deleteAllVertices();
00356
00357
00358 if(_VBHard.getNumVertices()!=0)
00359 _VBHard.setName("VegetableVB");
00360 }
00361 else
00362 _VBHard.deleteAllVertices();
00363
00364
00365 if(_VBHard.getNumVertices()==0)
00366 _VBHardOk= false;
00367 }
00368 }
00369
00370
00371 if(_VBHardOk)
00372 {
00373
00374
00375 lockBuffer();
00376
00377
00378 memcpy(_AGPBufferPtr, _RAMBufferPtr, _VBSoft.getVertexSize() * numVertices);
00379
00380
00381 if(!wasLocked)
00382 unlockBuffer();
00383 }
00384
00385
00386 }
00387
00388
00389
00390 void CVegetableVBAllocator::setupVBFormat()
00391 {
00392
00393 _VBSoft.clearValueEx();
00394
00395
00396 if( _Type == VBTypeLighted )
00397 {
00398 _VBSoft.addValueEx(NL3D_VEGETABLE_VPPOS_POS, CVertexBuffer::Float3);
00399 _VBSoft.addValueEx(NL3D_VEGETABLE_VPPOS_NORMAL, CVertexBuffer::Float3);
00400 _VBSoft.addValueEx(NL3D_VEGETABLE_VPPOS_BENDINFO, CVertexBuffer::Float3);
00401 }
00402
00403 else
00404 {
00405
00406 _VBSoft.addValueEx(NL3D_VEGETABLE_VPPOS_POS, CVertexBuffer::Float4);
00407
00408 _VBSoft.addValueEx(NL3D_VEGETABLE_VPPOS_BENDINFO, CVertexBuffer::Float4);
00409 }
00410 _VBSoft.addValueEx(NL3D_VEGETABLE_VPPOS_COLOR0, CVertexBuffer::UChar4);
00411 _VBSoft.addValueEx(NL3D_VEGETABLE_VPPOS_COLOR1, CVertexBuffer::UChar4);
00412 _VBSoft.addValueEx(NL3D_VEGETABLE_VPPOS_TEX0, CVertexBuffer::Float2);
00413 _VBSoft.addValueEx(NL3D_VEGETABLE_VPPOS_CENTER, CVertexBuffer::Float3);
00414 _VBSoft.initEx();
00415
00416 }
00417
00418
00419
00420 }