00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "stdopengl.h"
00027
00028 #include "driver_opengl_vertex_buffer_hard.h"
00029
00030
00031 using namespace std;
00032 using namespace NLMISC;
00033
00034 namespace NL3D
00035 {
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 IVertexArrayRange::IVertexArrayRange(CDriverGL *drv)
00053 {
00054 _Driver= drv;
00055 }
00056
00057 IVertexArrayRange::~IVertexArrayRange()
00058 {
00059 }
00060
00061
00062 IVertexBufferHardGL::IVertexBufferHardGL(CDriverGL *drv)
00063 {
00064 _Driver= drv;
00065 NVidiaVertexBufferHard= false;
00066 ATIVertexBufferHard= false;
00067 GPURenderingAfterFence= false;
00068 }
00069
00070 IVertexBufferHardGL::~IVertexBufferHardGL()
00071 {
00072 }
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 CVertexArrayRangeNVidia::CVertexArrayRangeNVidia(CDriverGL *drv) : IVertexArrayRange(drv)
00095 {
00096 _VertexArrayPtr= NULL;
00097 _VertexArraySize= 0;
00098 }
00099
00100
00101
00102 bool CVertexArrayRangeNVidia::allocate(uint32 size, IDriver::TVBHardType vbType)
00103 {
00104 nlassert(_VertexArrayPtr==NULL);
00105
00106 #ifdef NL_OS_WINDOWS
00107
00108 switch(vbType)
00109 {
00110 case IDriver::VBHardAGP:
00111 _VertexArrayPtr= wglAllocateMemoryNV(size, 0, 0, 0.5f);
00112 break;
00113 case IDriver::VBHardVRAM:
00114 _VertexArrayPtr= wglAllocateMemoryNV(size, 0, 0, 1.0f);
00115 break;
00116 };
00117 #endif // NL_OS_WINDOWS
00118
00119
00120
00121 if(_VertexArrayPtr)
00122 {
00123
00124
00125
00126 _HeapMemory.initHeap(_VertexArrayPtr, size, 8);
00127
00128
00129 _VertexArraySize= size;
00130 }
00131
00132
00133 return _VertexArrayPtr!=NULL;
00134 }
00135
00136
00137
00138 uint CVertexArrayRangeNVidia::sizeAllocated() const
00139 {
00140 return _VertexArraySize;
00141 }
00142
00143
00144
00145 void CVertexArrayRangeNVidia::free()
00146 {
00147
00148 if(_VertexArrayPtr)
00149 {
00150
00151 _HeapMemory.reset();
00152
00153
00154
00155 #ifdef NL_OS_WINDOWS
00156 wglFreeMemoryNV(_VertexArrayPtr);
00157 #endif // NL_OS_WINDOWS
00158
00159
00160 _VertexArrayPtr= NULL;
00161 _VertexArraySize= 0;
00162 }
00163 }
00164
00165
00166
00167 void CVertexArrayRangeNVidia::enable()
00168 {
00169
00170 if(_Driver->_CurrentVertexArrayRange!=this)
00171 {
00172
00173 if( _Driver->_NVCurrentVARSize != _VertexArraySize || _Driver->_NVCurrentVARPtr != _VertexArrayPtr)
00174 {
00175
00176 glFinish();
00177 nglVertexArrayRangeNV(_VertexArraySize, _VertexArrayPtr);
00178 glEnableClientState(GL_VERTEX_ARRAY_RANGE_NV);
00179 glVertexPointer(3,GL_FLOAT, 0, _VertexArrayPtr);
00180
00181 _Driver->_NVCurrentVARSize= _VertexArraySize;
00182 _Driver->_NVCurrentVARPtr= _VertexArrayPtr;
00183 }
00184
00185 glEnableClientState(_Driver->_Extensions.NVStateVARWithoutFlush);
00186 _Driver->_CurrentVertexArrayRange= this;
00187 }
00188 }
00189
00190
00191
00192 void CVertexArrayRangeNVidia::disable()
00193 {
00194
00195 if(_Driver->_CurrentVertexArrayRange!=NULL)
00196 {
00197
00198
00199 glDisableClientState(_Driver->_Extensions.NVStateVARWithoutFlush);
00200 _Driver->_CurrentVertexArrayRange= NULL;
00201 }
00202 }
00203
00204
00205
00206 void *CVertexArrayRangeNVidia::allocateVB(uint32 size)
00207 {
00208 return _HeapMemory.allocate(size);
00209 }
00210
00211
00212
00213 void CVertexArrayRangeNVidia::freeVB(void *ptr)
00214 {
00215 _HeapMemory.free(ptr);
00216 }
00217
00218
00219
00220 IVertexBufferHardGL *CVertexArrayRangeNVidia::createVBHardGL(uint16 vertexFormat, const uint8 *typeArray, uint32 numVertices)
00221 {
00222
00223 CVertexBufferHardGLNVidia *newVbHard= new CVertexBufferHardGLNVidia(_Driver);
00224
00225
00226 newVbHard->initFormat(vertexFormat, typeArray, numVertices);
00227
00228
00229 uint32 size= newVbHard->getVertexSize() * newVbHard->getNumVertices();
00230
00231
00232 void *vertexPtr;
00233 if( allocated() )
00234 {
00235 vertexPtr= allocateVB(size);
00236 }
00237
00238
00239 if( !vertexPtr )
00240 {
00241
00242 delete newVbHard;
00243 return NULL;
00244 }
00245 else
00246 {
00247
00248 newVbHard->initGL(this, vertexPtr);
00249 return newVbHard;
00250 }
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260 CVertexBufferHardGLNVidia::CVertexBufferHardGLNVidia(CDriverGL *drv) : IVertexBufferHardGL(drv)
00261 {
00262 _VertexArrayRange= NULL;
00263 _VertexPtr= NULL;
00264
00265 GPURenderingAfterFence= false;
00266 _FenceSet= false;
00267
00268
00269 NVidiaVertexBufferHard= true;
00270 }
00271
00272
00273
00274 CVertexBufferHardGLNVidia::~CVertexBufferHardGLNVidia()
00275 {
00276 if(_VertexArrayRange)
00277 {
00278
00279
00280 finishFence();
00281
00282 nglDeleteFencesNV(1, &_Fence);
00283
00284
00285 _VertexArrayRange->freeVB(_VertexPtr);
00286 _VertexPtr= NULL;
00287 _VertexArrayRange= NULL;
00288 }
00289 }
00290
00291
00292
00293 void CVertexBufferHardGLNVidia::initGL(CVertexArrayRangeNVidia *var, void *vertexPtr)
00294 {
00295 _VertexArrayRange= var;
00296 _VertexPtr= vertexPtr;
00297 nglGenFencesNV(1, &_Fence);
00298 }
00299
00300
00301
00302 void *CVertexBufferHardGLNVidia::lock()
00303 {
00304
00305
00306
00307 finishFence();
00308
00309 if(GPURenderingAfterFence)
00310 {
00311
00312 setFence();
00313
00314 finishFence();
00315
00316 GPURenderingAfterFence= false;
00317 }
00318
00319
00320 return _VertexPtr;
00321 }
00322
00323
00324
00325 void CVertexBufferHardGLNVidia::unlock()
00326 {
00327
00328 }
00329
00330
00331 void CVertexBufferHardGLNVidia::unlock(uint startVert, uint endVert)
00332 {
00333
00334
00335 }
00336
00337
00338 void CVertexBufferHardGLNVidia::enable()
00339 {
00340 if(_Driver->_CurrentVertexBufferHard != this)
00341 {
00342 nlassert(_VertexArrayRange);
00343 _VertexArrayRange->enable();
00344 _Driver->_CurrentVertexBufferHard= this;
00345 }
00346 }
00347
00348
00349
00350 void CVertexBufferHardGLNVidia::disable()
00351 {
00352 if(_Driver->_CurrentVertexBufferHard != NULL)
00353 {
00354 nlassert(_VertexArrayRange);
00355 _VertexArrayRange->disable();
00356 _Driver->_CurrentVertexBufferHard= NULL;
00357 }
00358 }
00359
00360
00361
00362 void CVertexBufferHardGLNVidia::setFence()
00363 {
00364 if(!isFenceSet())
00365 {
00366 nglSetFenceNV(_Fence, GL_ALL_COMPLETED_NV);
00367 _FenceSet= true;
00368 }
00369 }
00370
00371
00372 void CVertexBufferHardGLNVidia::finishFence()
00373 {
00374 if(isFenceSet())
00375 {
00376
00377 nglFinishFenceNV(_Fence);
00378 _FenceSet= false;
00379 }
00380 }
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 CVertexArrayRangeATI::CVertexArrayRangeATI(CDriverGL *drv) : IVertexArrayRange(drv)
00402 {
00403 _Allocated= false;
00404 _VertexObjectId= 0;
00405 _VertexArraySize= 0;
00406 }
00407
00408 bool CVertexArrayRangeATI::allocate(uint32 size, IDriver::TVBHardType vbType)
00409 {
00410 nlassert(!_Allocated);
00411
00412
00413 switch(vbType)
00414 {
00415 case IDriver::VBHardAGP:
00416 _VertexObjectId= nglNewObjectBufferATI(size, NULL, GL_DYNAMIC_ATI);
00417 break;
00418 case IDriver::VBHardVRAM:
00419 _VertexObjectId= nglNewObjectBufferATI(size, NULL, GL_STATIC_ATI);
00420 break;
00421 };
00422
00423
00424
00425 if( nglIsObjectBufferATI(_VertexObjectId) )
00426 {
00427 _Allocated= true;
00428
00429
00430
00431 _HeapMemory.initHeap((void*)NL3D_DRV_ATI_FAKE_MEM_START, size, 8);
00432
00433
00434 _VertexArraySize= size;
00435
00436
00437 return true;
00438 }
00439 else
00440 {
00441
00442 return false;
00443 }
00444 }
00445
00446 uint CVertexArrayRangeATI::sizeAllocated() const
00447 {
00448 return _VertexArraySize;
00449 }
00450
00451 void CVertexArrayRangeATI::free()
00452 {
00453
00454 if(_Allocated)
00455 {
00456
00457 _HeapMemory.reset();
00458
00459
00460 nglDeleteObjectBufferATI(_VertexObjectId);
00461
00462 _Allocated= false;
00463 _VertexArraySize= 0;
00464 }
00465 }
00466
00467 IVertexBufferHardGL *CVertexArrayRangeATI::createVBHardGL(uint16 vertexFormat, const uint8 *typeArray, uint32 numVertices)
00468 {
00469
00470 CVertexBufferHardGLATI *newVbHard= new CVertexBufferHardGLATI(_Driver);
00471
00472
00473 newVbHard->initFormat(vertexFormat, typeArray, numVertices);
00474
00475
00476 uint32 size= newVbHard->getVertexSize() * newVbHard->getNumVertices();
00477
00478
00479 void *vertexPtr =NULL;
00480 if( _Allocated )
00481 {
00482 vertexPtr= allocateVB(size);
00483 }
00484
00485
00486 if( !vertexPtr )
00487 {
00488
00489 delete newVbHard;
00490 return NULL;
00491 }
00492 else
00493 {
00494
00495 if( newVbHard->createRAMMirror(size) )
00496 {
00497
00498 newVbHard->initGL(this, vertexPtr);
00499 return newVbHard;
00500 }
00501 else
00502 {
00503
00504 delete newVbHard;
00505 return NULL;
00506 }
00507 }
00508 }
00509
00510 void CVertexArrayRangeATI::enable()
00511 {
00512
00513 _Driver->_CurrentVertexArrayRange= this;
00514 }
00515
00516 void CVertexArrayRangeATI::disable()
00517 {
00518
00519 _Driver->_CurrentVertexArrayRange= NULL;
00520 }
00521
00522 void *CVertexArrayRangeATI::allocateVB(uint32 size)
00523 {
00524 return _HeapMemory.allocate(size);
00525 }
00526
00527 void CVertexArrayRangeATI::freeVB(void *ptr)
00528 {
00529 _HeapMemory.free(ptr);
00530 }
00531
00532
00533
00534
00535
00536
00537
00538
00539 CVertexBufferHardGLATI::CVertexBufferHardGLATI(CDriverGL *drv) : IVertexBufferHardGL(drv)
00540 {
00541 _VertexArrayRange= NULL;
00542 _VertexPtr= NULL;
00543 _RAMMirrorVertexPtr= NULL;
00544 _RAMMirrorVertexSize= 0;
00545
00546
00547 ATIVertexBufferHard= true;
00548 }
00549
00550
00551
00552 CVertexBufferHardGLATI::~CVertexBufferHardGLATI()
00553 {
00554 if(_VertexArrayRange)
00555 {
00556
00557 _VertexArrayRange->freeVB(_VertexPtr);
00558 _VertexPtr= NULL;
00559 _VertexArrayRange= NULL;
00560 }
00561
00562 if(_RAMMirrorVertexPtr)
00563 {
00564 delete [] ((uint8*)_RAMMirrorVertexPtr);
00565 _RAMMirrorVertexPtr= NULL;
00566 _RAMMirrorVertexSize= 0;
00567 }
00568 }
00569
00570
00571
00572 bool CVertexBufferHardGLATI::createRAMMirror(uint memSize)
00573 {
00574
00575 if(_RAMMirrorVertexPtr)
00576 {
00577 free(_RAMMirrorVertexPtr);
00578 _RAMMirrorVertexPtr= NULL;
00579 _RAMMirrorVertexSize= 0;
00580 }
00581
00582 _RAMMirrorVertexPtr = (void*)new uint8[memSize];
00583 if(_RAMMirrorVertexPtr)
00584 {
00585 _RAMMirrorVertexSize= memSize;
00586 return true;
00587 }
00588 else
00589 return false;
00590 }
00591
00592
00593
00594 void CVertexBufferHardGLATI::initGL(CVertexArrayRangeATI *var, void *vertexPtr)
00595 {
00596 _VertexArrayRange= var;
00597 _VertexPtr= vertexPtr;
00598 }
00599
00600
00601
00602 void *CVertexBufferHardGLATI::lock()
00603 {
00604
00605 return _RAMMirrorVertexPtr;
00606 }
00607
00608
00609
00610 void CVertexBufferHardGLATI::unlock()
00611 {
00612
00613 nglUpdateObjectBufferATI(getATIVertexObjectId(), (uint)_VertexPtr - NL3D_DRV_ATI_FAKE_MEM_START,
00614 _RAMMirrorVertexSize, _RAMMirrorVertexPtr, GL_PRESERVE_ATI);
00615 }
00616
00617
00618
00619 void CVertexBufferHardGLATI::unlock(uint startVert, uint endVert)
00620 {
00621
00622 if(endVert>getNumVertices())
00623 endVert=getNumVertices();
00624
00625
00626 if(startVert>=endVert)
00627 return;
00628
00629
00630 uint size= (endVert-startVert)*getVertexSize();
00631 uint srcOffStart= startVert*getVertexSize();
00632 uint dstOffStart= ((uint)_VertexPtr - NL3D_DRV_ATI_FAKE_MEM_START) + srcOffStart;
00633
00634 nglUpdateObjectBufferATI(getATIVertexObjectId(), dstOffStart,
00635 size, (uint8*)_RAMMirrorVertexPtr + srcOffStart, GL_PRESERVE_ATI);
00636 }
00637
00638
00639
00640 void CVertexBufferHardGLATI::enable()
00641 {
00642 if(_Driver->_CurrentVertexBufferHard != this)
00643 {
00644 nlassert(_VertexArrayRange);
00645 _VertexArrayRange->enable();
00646 _Driver->_CurrentVertexBufferHard= this;
00647 }
00648 }
00649
00650
00651
00652 void CVertexBufferHardGLATI::disable()
00653 {
00654 if(_Driver->_CurrentVertexBufferHard != NULL)
00655 {
00656 nlassert(_VertexArrayRange);
00657 _VertexArrayRange->disable();
00658 _Driver->_CurrentVertexBufferHard= NULL;
00659 }
00660 }
00661
00662
00663 }
00664