00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00042
00043
00044 #define NL3D_VEGETABLE_VERTEX_ALLOCATE_SECURITY 1024
00045
00046
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
00061 _VertexFreeMemory.reserve(NL3D_VEGETABLE_VERTEX_FREE_MEMORY_RESERVE);
00062 _NumVerticesAllocated= 0;
00063
00064
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
00078 setupVBFormat();
00079 }
00080
00081
00082
00083 CVegetableVBAllocator::~CVegetableVBAllocator()
00084 {
00085 clear();
00086 }
00087
00088
00089 void CVegetableVBAllocator::updateDriver(IDriver *driver)
00090 {
00091
00092 nlassert(driver && !_BufferLocked);
00093
00094 if( _Driver==NULL || driver!=_Driver )
00095 {
00096
00097 deleteVertexBufferHard();
00098 _Driver= driver;
00099 _VBHardOk= (_MaxVertexInBufferHard>0) && (_Driver->supportVertexBufferHard());
00100
00101
00102 nlassert(_Driver->isVertexProgramSupported());
00103
00104
00105 if( _NumVerticesAllocated>0 )
00106 allocateVertexBufferAndFillVBHard(_NumVerticesAllocated);
00107 }
00108 else
00109 {
00110
00111 if( _VBHardOk && _VBHard==NULL && _NumVerticesAllocated>0 )
00112 allocateVertexBufferAndFillVBHard(_NumVerticesAllocated);
00113 }
00114
00115 }
00116
00117
00118 void CVegetableVBAllocator::clear()
00119 {
00120
00121 _VertexFreeMemory.clear();
00122 _NumVerticesAllocated= 0;
00123
00124
00125 deleteVertexBufferHard();
00126
00127 _VB.deleteAllVertices();
00128
00129
00130 _Driver= NULL;
00131 _VBHardOk= false;
00132 }
00133
00134
00135
00136 void CVegetableVBAllocator::lockBuffer()
00137 {
00138
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
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
00180 if( _VertexFreeMemory.size()==0 )
00181 {
00182
00183 uint newResize;
00184 if(_NumVerticesAllocated==0)
00185 newResize= NL3D_VEGETABLE_VERTEX_ALLOCATE_START;
00186 else
00187 newResize= NL3D_VEGETABLE_VERTEX_ALLOCATE_SECURITY;
00188
00189 if(_NumVerticesAllocated<_MaxVertexInBufferHard && _NumVerticesAllocated+newResize > _MaxVertexInBufferHard)
00190 {
00191 newResize= _MaxVertexInBufferHard - _NumVerticesAllocated;
00192 }
00193 _NumVerticesAllocated+= newResize;
00194
00195 allocateVertexBufferAndFillVBHard(_NumVerticesAllocated);
00196
00197 _VertexInfos.resize(_NumVerticesAllocated);
00198
00199
00200 for(uint i=0;i<newResize;i++)
00201 {
00202
00203
00204 _VertexFreeMemory.push_back( _NumVerticesAllocated - (i+1) );
00205
00206
00207 _VertexInfos[_NumVerticesAllocated - (i+1)].Free= true;
00208 }
00209 }
00210
00211
00212 uint id= _VertexFreeMemory.back();
00213
00214 _VertexFreeMemory.pop_back();
00215
00216
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
00229 nlassert(vid<_NumVerticesAllocated);
00230 nlassert(!_VertexInfos[vid].Free);
00231 _VertexInfos[vid].Free= true;
00232
00233
00234
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
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
00264 if(_VBHard)
00265 _Driver->activeVertexBufferHard(_VBHard);
00266 else
00267 _Driver->activeVertexBuffer(_VB);
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 void CVegetableVBAllocator::deleteVertexBufferHard()
00280 {
00281
00282 unlockBuffer();
00283
00284
00285 if(_VBHard!=NULL)
00286 {
00287
00288 nlassert(_Driver!=NULL);
00289
00290
00291 _Driver->deleteVertexBufferHard(_VBHard);
00292 _VBHard= NULL;
00293 }
00294
00295 }
00296
00297
00298 void CVegetableVBAllocator::allocateVertexBufferAndFillVBHard(uint32 numVertices)
00299 {
00300
00301 _VB.setNumVertices(numVertices);
00302
00303
00304 nlassert(_Driver);
00305
00306
00307 bool wasLocked= bufferLocked();
00308 unlockBuffer();
00309
00310
00311 if( _VBHardOk )
00312 {
00313
00314 if(_VBHard!=NULL)
00315 {
00316
00317 nlassert(_Driver!=NULL);
00318 _Driver->deleteVertexBufferHard(_VBHard);
00319 }
00320
00321
00322
00323 if(numVertices <= _MaxVertexInBufferHard)
00324 _VBHard= _Driver->createVertexBufferHard(_VB.getVertexFormat(), _VB.getValueTypePointer(), numVertices, IDriver::VBHardAGP);
00325 else
00326 _VBHard= NULL;
00327
00328
00329 if(_VBHard==NULL)
00330 _VBHardOk= false;
00331 else
00332 {
00333
00334
00335 lockBuffer();
00336
00337
00338 memcpy(_AGPBufferPtr, _VB.getVertexCoordPointer(0), _VB.getVertexSize() * numVertices);
00339
00340
00341 if(!wasLocked)
00342 unlockBuffer();
00343 }
00344 }
00345
00346
00347 }
00348
00349
00350
00351 void CVegetableVBAllocator::setupVBFormat()
00352 {
00353
00354 _VB.clearValueEx();
00355
00356
00357 if( _Type == VBTypeLighted )
00358 {
00359 _VB.addValueEx(NL3D_VEGETABLE_VPPOS_POS, CVertexBuffer::Float3);
00360 _VB.addValueEx(NL3D_VEGETABLE_VPPOS_NORMAL, CVertexBuffer::Float3);
00361 _VB.addValueEx(NL3D_VEGETABLE_VPPOS_BENDINFO, CVertexBuffer::Float3);
00362 }
00363
00364 else
00365 {
00366
00367 _VB.addValueEx(NL3D_VEGETABLE_VPPOS_POS, CVertexBuffer::Float4);
00368
00369 _VB.addValueEx(NL3D_VEGETABLE_VPPOS_BENDINFO, CVertexBuffer::Float4);
00370 }
00371 _VB.addValueEx(NL3D_VEGETABLE_VPPOS_COLOR0, CVertexBuffer::UChar4);
00372 _VB.addValueEx(NL3D_VEGETABLE_VPPOS_COLOR1, CVertexBuffer::UChar4);
00373 _VB.addValueEx(NL3D_VEGETABLE_VPPOS_TEX0, CVertexBuffer::Float2);
00374 _VB.addValueEx(NL3D_VEGETABLE_VPPOS_CENTER, CVertexBuffer::Float3);
00375 _VB.initEx();
00376
00377 }
00378
00379
00380
00381 }