driver_opengl_vertex_buffer_hard.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2000-2002 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 #include "stdopengl.h"
00025 
00026 #include "driver_opengl.h"
00027 #include "driver_opengl_vertex_buffer_hard.h"
00028 
00029 #include "nel/3d/vertex_buffer.h"
00030 
00031 using   namespace std;
00032 using   namespace NLMISC;
00033 
00034 namespace NL3D
00035 {
00036 
00037 
00038 
00039 
00040 // ***************************************************************************
00041 // ***************************************************************************
00042 // ***************************************************************************
00043 //
00044 // VBHard interface for both NVidia / ATI extension.
00045 //
00046 // ***************************************************************************
00047 // ***************************************************************************
00048 // ***************************************************************************
00049 
00050 
00051 
00052 // ***************************************************************************
00053 IVertexArrayRange::IVertexArrayRange(CDriverGL *drv)
00054 {
00055     H_AUTO_OGL(IVertexArrayRange_IVertexArrayRange)
00056     _Driver= drv;
00057 }
00058 // ***************************************************************************
00059 IVertexArrayRange::~IVertexArrayRange()
00060 {
00061     H_AUTO_OGL(IVertexArrayRange_IVertexArrayRangeDtor)
00062 }
00063 
00064 // ***************************************************************************
00065 IVertexBufferHardGL::IVertexBufferHardGL(CDriverGL *drv, CVertexBuffer *vb) : VB (vb)
00066 {
00067     H_AUTO_OGL(IVertexBufferHardGL_IVertexBufferHardGL)
00068     _Driver= drv;
00069     GPURenderingAfterFence= false;
00070     VBType = UnknownVB;
00071     _Invalid = false;
00072 }
00073 // ***************************************************************************
00074 IVertexBufferHardGL::~IVertexBufferHardGL()
00075 {
00076     H_AUTO_OGL(IVertexBufferHardGL_IVertexBufferHardGLDtor)
00077 }
00078 
00079 
00080 
00081 // ***************************************************************************
00082 // ***************************************************************************
00083 // ***************************************************************************
00084 //
00085 // NVidia implementation
00086 //
00087 // ***************************************************************************
00088 // ***************************************************************************
00089 // ***************************************************************************
00090 
00091 
00092 
00093 // ***************************************************************************
00094 // CVertexArrayRangeNVidia
00095 // ***************************************************************************
00096 
00097 
00098 // ***************************************************************************
00099 CVertexArrayRangeNVidia::CVertexArrayRangeNVidia(CDriverGL *drv) : IVertexArrayRange(drv)
00100 {
00101     H_AUTO_OGL(CVertexArrayRangeNVidia_CVertexArrayRangeNVidia)
00102     _VertexArrayPtr= NULL;
00103     _VertexArraySize= 0;
00104 }
00105 
00106 
00107 // ***************************************************************************
00108 bool            CVertexArrayRangeNVidia::allocate(uint32 size, CVertexBuffer::TPreferredMemory vbType)
00109 {
00110     H_AUTO_OGL(CVertexArrayRangeNVidia_allocate)
00111     nlassert(_VertexArrayPtr==NULL);
00112 
00113 #ifdef  NL_OS_WINDOWS
00114     // try to allocate AGP or VRAM data.
00115     switch(vbType)
00116     {
00117     case CVertexBuffer::AGPPreferred:
00118         _VertexArrayPtr= nwglAllocateMemoryNV(size, 0, 0, 0.5f);
00119         break;
00120     case CVertexBuffer::StaticPreferred:
00121         if (_Driver->getStaticMemoryToVRAM())
00122             _VertexArrayPtr= nwglAllocateMemoryNV(size, 0, 0, 1.0f);
00123         else
00124             _VertexArrayPtr= nwglAllocateMemoryNV(size, 0, 0, 0.5f);
00125         break;
00126     };
00127 #endif  // NL_OS_WINDOWS
00128 
00129 
00130     // init the allocator.
00131     if(_VertexArrayPtr)
00132     {
00133         /* Init with an alignment of 8. Not sure it is useful, but GDC01_Performance.pdf papers talks about
00134           "Data arrays must be 8-byte aligned". Don't know what "Data" is.
00135         */
00136         _HeapMemory.initHeap(_VertexArrayPtr, size, 8);
00137 
00138         // set the size
00139         _VertexArraySize= size;
00140     }
00141 
00142 
00143     return _VertexArrayPtr!=NULL;
00144 }
00145 
00146 
00147 // ***************************************************************************
00148 uint            CVertexArrayRangeNVidia::sizeAllocated() const
00149 {
00150     H_AUTO_OGL(CVertexArrayRangeNVidia_sizeAllocated)
00151     return _VertexArraySize;
00152 }
00153 
00154 
00155 // ***************************************************************************
00156 void            CVertexArrayRangeNVidia::free()
00157 {
00158     H_AUTO_OGL(CVertexArrayRangeNVidia_free)
00159     // release the ptr.
00160     if(_VertexArrayPtr)
00161     {
00162         // reset the allocator.
00163         _HeapMemory.reset();
00164 
00165 #ifdef  NL_OS_WINDOWS
00166         // Free special memory.
00167         nwglFreeMemoryNV(_VertexArrayPtr);
00168 #endif  // NL_OS_WINDOWS
00169 
00170         _VertexArrayPtr= NULL;
00171         _VertexArraySize= 0;
00172     }
00173 }
00174 
00175 
00176 // ***************************************************************************
00177 void            CVertexArrayRangeNVidia::enable()
00178 {
00179     H_AUTO_OGL(CVertexArrayRangeNVidia_enable)
00180     // if not already enabled.
00181     if(_Driver->_CurrentVertexArrayRange!=this)
00182     {
00183         // Setup the ptrs only if differnets from last time (may rarely happens)
00184         if( _Driver->_NVCurrentVARSize != _VertexArraySize || _Driver->_NVCurrentVARPtr != _VertexArrayPtr)
00185         {
00186             // Yoyo: NVidia Bug ?? must do this strange thing, this ensure that it is correclty setuped.
00187             glFinish();
00188             nglVertexArrayRangeNV(_VertexArraySize, _VertexArrayPtr);
00189             glEnableClientState(GL_VERTEX_ARRAY_RANGE_NV);
00190             glVertexPointer(3,GL_FLOAT, 0, _VertexArrayPtr);
00191             // cache.
00192             _Driver->_NVCurrentVARSize= _VertexArraySize;
00193             _Driver->_NVCurrentVARPtr= _VertexArrayPtr;
00194         }
00195         // enable VAR. NB: flush is unesufull, so don't flush if extension is OK
00196         glEnableClientState(_Driver->_Extensions.NVStateVARWithoutFlush);
00197         _Driver->_CurrentVertexArrayRange= this;
00198     }
00199 }
00200 
00201 
00202 // ***************************************************************************
00203 void            CVertexArrayRangeNVidia::disable()
00204 {
00205     H_AUTO_OGL(CVertexArrayRangeNVidia_disable)
00206     // if not already disabled.
00207     if(_Driver->_CurrentVertexArrayRange!=NULL)
00208     {
00209         // just disable the state, don't change VAR ptr setup.
00210         // NB: flush is unesufull, so don't flush if extension is OK
00211         glDisableClientState(_Driver->_Extensions.NVStateVARWithoutFlush);
00212         _Driver->_CurrentVertexArrayRange= NULL;
00213     }
00214 }
00215 
00216 
00217 // ***************************************************************************
00218 void            *CVertexArrayRangeNVidia::allocateVB(uint32 size)
00219 {
00220     H_AUTO_OGL(CVertexArrayRangeNVidia_allocateVB)
00221     return _HeapMemory.allocate(size);
00222 }
00223 
00224 
00225 // ***************************************************************************
00226 void            CVertexArrayRangeNVidia::freeVB(void    *ptr)
00227 {
00228     H_AUTO_OGL(CVertexArrayRangeNVidia_freeVB)
00229     _HeapMemory.free(ptr);
00230 }
00231 
00232 
00233 // ***************************************************************************
00234 IVertexBufferHardGL     *CVertexArrayRangeNVidia::createVBHardGL(uint size, CVertexBuffer *vb)
00235 {
00236     H_AUTO_OGL(CVertexArrayRangeNVidia_createVBHardGL)
00237     // create a NVidia VBHard
00238     CVertexBufferHardGLNVidia   *newVbHard= new CVertexBufferHardGLNVidia(_Driver, vb);
00239 
00240     // try to allocate
00241     void    *vertexPtr = 0;
00242     if( allocated() )
00243     {
00244          vertexPtr= allocateVB(size);
00245     }
00246 
00247     // If allocation fails.
00248     if( !vertexPtr )
00249     {
00250         // just destroy this object (no free()).
00251         delete newVbHard;
00252         return NULL;
00253     }
00254     else
00255     {
00256         // Ok, setup, and allocate the fence.
00257         newVbHard->initGL(this, vertexPtr);
00258         return newVbHard;
00259     }
00260 }
00261 
00262 
00263 // ***************************************************************************
00264 // CVertexBufferHardGLNVidia
00265 // ***************************************************************************
00266 
00267 
00268 // ***************************************************************************
00269 CVertexBufferHardGLNVidia::CVertexBufferHardGLNVidia(CDriverGL *drv, CVertexBuffer *vb) : IVertexBufferHardGL(drv, vb)
00270 {
00271     H_AUTO_OGL(CVertexBufferHardGLNVidia_CVertexBufferHardGLNVidia)
00272     _VertexArrayRange= NULL;
00273     _VertexPtr= NULL;
00274 
00275     GPURenderingAfterFence= false;
00276     _FenceSet= false;
00277 
00278     // Flag our type
00279     VBType = NVidiaVB;
00280 
00281     // default: dynamic Loick
00282     _LockHintStatic= false;
00283 }
00284 
00285 
00286 // ***************************************************************************
00287 CVertexBufferHardGLNVidia::~CVertexBufferHardGLNVidia()
00288 {
00289     H_AUTO_OGL(CVertexBufferHardGLNVidia_CVertexBufferHardGLNVidiaDtor)
00290     if(_VertexArrayRange)
00291     {
00292         // Destroy Fence.
00293         // First wait for completion.
00294         finishFence();
00295         // then delete.
00296         nglDeleteFencesNV(1, &_Fence);
00297 
00298         // Then free the VAR.
00299         _VertexArrayRange->freeVB(_VertexPtr);
00300         _VertexPtr= NULL;
00301         _VertexArrayRange= NULL;
00302     }
00303 }
00304 
00305 
00306 // ***************************************************************************
00307 void        CVertexBufferHardGLNVidia::initGL(CVertexArrayRangeNVidia *var, void *vertexPtr)
00308 {
00309     H_AUTO_OGL(CVertexBufferHardGLNVidia_initGL)
00310     _VertexArrayRange= var;
00311     _VertexPtr= vertexPtr;
00312     nglGenFencesNV(1, &_Fence);
00313 }
00314 
00315 
00316 // ***************************************************************************
00317 void        *CVertexBufferHardGLNVidia::lock()
00318 {
00319     H_AUTO_OGL(CVertexBufferHardGLNVidia_lock)
00320     // sync the 3d card with the system.
00321 
00322     // If the user lock an activated VBHard, after rendering some primitives, we must stall the CPU
00323     // Also always do this for Static Lock VBHard (because no setFence are inserted after rendering
00324     if(GPURenderingAfterFence || _LockHintStatic)
00325     {
00326         // Set a new fence at the current position in the command stream, replacing the old one
00327         setFence();
00328         // And so the GPU has rendered all our primitives.
00329         GPURenderingAfterFence= false;
00330     }
00331 
00332     // Lock Profile?
00333     TTicks  beforeLock = 0;
00334     if(_Driver->_VBHardProfiling)
00335     {
00336         beforeLock= CTime::getPerformanceTime();
00337     }
00338 
00339     // Ensure the GPU has finished with the current VBHard.
00340     finishFence();
00341 
00342     // Lock Profile?
00343     if(_Driver->_VBHardProfiling)
00344     {
00345         TTicks  afterLock;
00346         afterLock= CTime::getPerformanceTime();
00347         _Driver->appendVBHardLockProfile(afterLock-beforeLock, VB);
00348     }
00349 
00350     return _VertexPtr;
00351 }
00352 
00353 
00354 // ***************************************************************************
00355 void        CVertexBufferHardGLNVidia::unlock()
00356 {
00357     H_AUTO_OGL(CVertexBufferHardGLNVidia_unlock)
00358     // no op.
00359 }
00360 
00361 // ***************************************************************************
00362 void        CVertexBufferHardGLNVidia::unlock(uint /* start */, uint /* end */)
00363 {
00364     H_AUTO_OGL(CVertexBufferHardGLNVidia_unlock_start_end)
00365     // no op.
00366     // NB: start-end only useful for ATI ext.
00367 }
00368 
00369 // ***************************************************************************
00370 void        *CVertexBufferHardGLNVidia::getPointer()
00371 {
00372     H_AUTO_OGL(CVertexBufferHardGLNVidia_getPointer)
00373     return _VertexPtr;
00374 }
00375 
00376 // ***************************************************************************
00377 void            CVertexBufferHardGLNVidia::enable()
00378 {
00379     H_AUTO_OGL(CVertexBufferHardGLNVidia_enable)
00380     if(_Driver->_CurrentVertexBufferHard != this)
00381     {
00382         nlassert(_VertexArrayRange);
00383         _VertexArrayRange->enable();
00384         _Driver->_CurrentVertexBufferHard= this;
00385     }
00386 }
00387 
00388 
00389 // ***************************************************************************
00390 void            CVertexBufferHardGLNVidia::disable()
00391 {
00392     H_AUTO_OGL(CVertexBufferHardGLNVidia_disbale)
00393     if(_Driver->_CurrentVertexBufferHard != NULL)
00394     {
00395         nlassert(_VertexArrayRange);
00396         _VertexArrayRange->disable();
00397         _Driver->_CurrentVertexBufferHard= NULL;
00398     }
00399 }
00400 
00401 // ***************************************************************************
00402 void            CVertexBufferHardGLNVidia::lockHintStatic(bool staticLock)
00403 {
00404     H_AUTO_OGL(CVertexBufferHardGLNVidia_lockHintStatic)
00405     // Store the flag.
00406     _LockHintStatic= staticLock;
00407 }
00408 
00409 // ***************************************************************************
00410 
00411 void CVertexBufferHardGLNVidia::setupVBInfos(CVertexBufferInfo &vb)
00412 {
00413     H_AUTO_OGL(CVertexBufferHardGLNVidia_setupVBInfos)
00414     vb.VBMode = CVertexBufferInfo::HwNVIDIA;
00415 }
00416 
00417 // ***************************************************************************
00418 void            CVertexBufferHardGLNVidia::setFence()
00419 {
00420     H_AUTO_OGL(CVertexBufferHardGLNVidia_setFence)
00421     // NB: if the Fence was set and not finished, then the new one will KICK the old.
00422     nglSetFenceNV(_Fence, GL_ALL_COMPLETED_NV);
00423     _FenceSet= true;
00424 }
00425 
00426 // ***************************************************************************
00427 void            CVertexBufferHardGLNVidia::finishFence()
00428 {
00429     H_AUTO_OGL(CVertexBufferHardGLNVidia_finishFence)
00430     if(isFenceSet())
00431     {
00432         // Stall CPU while the fence command is not reached in the GPU command stream.
00433         nglFinishFenceNV(_Fence);
00434         _FenceSet= false;
00435     }
00436 }
00437 
00438 // ***************************************************************************
00439 void            CVertexBufferHardGLNVidia::testFence()
00440 {
00441 
00442     H_AUTO_OGL(CVertexBufferHardGLNVidia_testFence)
00443     if(isFenceSet())
00444     {
00445         // Don't stall the CPU
00446         GLboolean   b= nglTestFenceNV(_Fence);
00447         // if completed
00448         if(b==GL_TRUE)
00449             _FenceSet= false;
00450     }
00451 }
00452 
00453 
00454 
00455 // ***************************************************************************
00456 // ***************************************************************************
00457 // ***************************************************************************
00458 //
00459 // ATI implementation
00460 //
00461 // ***************************************************************************
00462 // ***************************************************************************
00463 // ***************************************************************************
00464 
00465 
00466 // ***************************************************************************
00467 // CVertexArrayRangeATI
00468 // ***************************************************************************
00469 
00470 
00471 // ***************************************************************************
00472 CVertexArrayRangeATI::CVertexArrayRangeATI(CDriverGL *drv) : IVertexArrayRange(drv)
00473 {
00474     H_AUTO_OGL(CVertexArrayRangeATI_CVertexArrayRangeATI)
00475     _Allocated= false;
00476     _VertexObjectId= 0;
00477     _VertexArraySize= 0;
00478 }
00479 // ***************************************************************************
00480 bool                    CVertexArrayRangeATI::allocate(uint32 size, CVertexBuffer::TPreferredMemory vbType)
00481 {
00482     H_AUTO_OGL(CVertexArrayRangeATI_allocate)
00483     nlassert(!_Allocated);
00484 
00485     // try to allocate AGP (suppose mean ATI dynamic) or VRAM (suppose mean ATI static) data.
00486     switch(vbType)
00487     {
00488     case CVertexBuffer::AGPPreferred:
00489         _VertexObjectId= nglNewObjectBufferATI(size, NULL, GL_DYNAMIC_ATI);
00490         break;
00491     case CVertexBuffer::StaticPreferred:
00492         if (_Driver->getStaticMemoryToVRAM())
00493             _VertexObjectId= nglNewObjectBufferATI(size, NULL, GL_STATIC_ATI);
00494         else
00495             _VertexObjectId= nglNewObjectBufferATI(size, NULL, GL_DYNAMIC_ATI);
00496         break;
00497     default:
00498         break;
00499     };
00500 
00501 
00502     // init the allocator, if success
00503     if( nglIsObjectBufferATI(_VertexObjectId) )
00504     {
00505         _Allocated= true;
00506         /* Init with an alignment of 8. Not sure if it is useful.
00507             Init With a FAKE memory starting at NL3D_DRV_ATI_FAKE_MEM_START
00508         */
00509         _HeapMemory.initHeap((void*)NL3D_DRV_ATI_FAKE_MEM_START, size, 8);
00510 
00511         // set the size
00512         _VertexArraySize= size;
00513 
00514         // Ok!
00515         return true;
00516     }
00517     else
00518     {
00519         // failure.
00520         return false;
00521     }
00522 }
00523 // ***************************************************************************
00524 uint                    CVertexArrayRangeATI::sizeAllocated() const
00525 {
00526     H_AUTO_OGL(CVertexArrayRangeATI_sizeAllocated)
00527     return _VertexArraySize;
00528 }
00529 // ***************************************************************************
00530 void                    CVertexArrayRangeATI::free()
00531 {
00532     H_AUTO_OGL(CVertexArrayRangeATI_free)
00533     // release the ptr.
00534     if(_Allocated)
00535     {
00536         // reset the allocator.
00537         _HeapMemory.reset();
00538 
00539         // Free special memory.
00540         nglDeleteObjectBufferATI(_VertexObjectId);
00541 
00542         _Allocated= false;
00543         _VertexArraySize= 0;
00544     }
00545 }
00546 // ***************************************************************************
00547 IVertexBufferHardGL     *CVertexArrayRangeATI::createVBHardGL(uint size, CVertexBuffer *vb)
00548 {
00549     H_AUTO_OGL(CVertexArrayRangeATI_createVBHardGL)
00550     // create a ATI VBHard
00551     CVertexBufferHardGLATI  *newVbHard= new CVertexBufferHardGLATI(_Driver, vb);
00552 
00553     // try to allocate
00554     void    *vertexPtr =NULL;
00555     if( _Allocated )
00556     {
00557          vertexPtr= allocateVB(size);
00558     }
00559 
00560     // If allocation fails.
00561     if( !vertexPtr )
00562     {
00563         // just destroy this object (no free()).
00564         delete newVbHard;
00565         return NULL;
00566     }
00567     else
00568     {
00569         // Then try to create a RAM mirror in the VB.
00570         if( newVbHard->createRAMMirror(size) )
00571         {
00572             // Ok, setup
00573             newVbHard->initGL(this, vertexPtr);
00574             return newVbHard;
00575         }
00576         else
00577         {
00578             // Discard the VB.
00579             delete newVbHard;
00580             return NULL;
00581         }
00582     }
00583 }
00584 // ***************************************************************************
00585 void            CVertexArrayRangeATI::enable()
00586 {
00587     H_AUTO_OGL(CVertexArrayRangeATI_enable)
00588     // No-op for ATI !!!
00589     _Driver->_CurrentVertexArrayRange= this;
00590 }
00591 // ***************************************************************************
00592 void            CVertexArrayRangeATI::disable()
00593 {
00594     H_AUTO_OGL(CVertexArrayRangeATI_disable)
00595     // No-op for ATI !!!
00596     _Driver->_CurrentVertexArrayRange= NULL;
00597 }
00598 // ***************************************************************************
00599 void            *CVertexArrayRangeATI::allocateVB(uint32 size)
00600 {
00601     H_AUTO_OGL(CVertexArrayRangeATI_allocateVB)
00602     return _HeapMemory.allocate(size);
00603 }
00604 // ***************************************************************************
00605 void            CVertexArrayRangeATI::freeVB(void   *ptr)
00606 {
00607     H_AUTO_OGL(CVertexArrayRangeATI_freeVB)
00608     _HeapMemory.free(ptr);
00609 }
00610 
00611 
00612 // ***************************************************************************
00613 // CVertexBufferHardGLATI
00614 // ***************************************************************************
00615 
00616 
00617 // ***************************************************************************
00618 CVertexBufferHardGLATI::CVertexBufferHardGLATI(CDriverGL *drv, CVertexBuffer *vb) : IVertexBufferHardGL(drv, vb)
00619 {
00620     H_AUTO_OGL(CVertexBufferHardGLATI_CVertexBufferHardGLATI)
00621     _VertexArrayRange= NULL;
00622     _VertexPtr= NULL;
00623     _RAMMirrorVertexPtr= NULL;
00624     _RAMMirrorVertexSize= 0;
00625 
00626     // Flag our type
00627     VBType = ATIVB;
00628 }
00629 
00630 
00631 // ***************************************************************************
00632 CVertexBufferHardGLATI::~CVertexBufferHardGLATI()
00633 {
00634     H_AUTO_OGL(CVertexBufferHardGLATI_CVertexBufferHardGLATIDtor)
00635     if(_VertexArrayRange)
00636     {
00637         // free the VAR.
00638         _VertexArrayRange->freeVB(_VertexPtr);
00639         _VertexPtr= NULL;
00640         _VertexArrayRange= NULL;
00641     }
00642 
00643     if(_RAMMirrorVertexPtr)
00644     {
00645         delete [] ((uint8*)_RAMMirrorVertexPtr);
00646         _RAMMirrorVertexPtr= NULL;
00647         _RAMMirrorVertexSize= 0;
00648     }
00649 }
00650 
00651 
00652 // ***************************************************************************
00653 bool        CVertexBufferHardGLATI::createRAMMirror(uint memSize)
00654 {
00655     H_AUTO_OGL(CVertexBufferHardGLATI_createRAMMirror)
00656     // delete old if any
00657     if(_RAMMirrorVertexPtr)
00658     {
00659         free(_RAMMirrorVertexPtr);
00660         _RAMMirrorVertexPtr= NULL;
00661         _RAMMirrorVertexSize= 0;
00662     }
00663     // create
00664     _RAMMirrorVertexPtr = (void*)new uint8[memSize];
00665     if(_RAMMirrorVertexPtr)
00666     {
00667         _RAMMirrorVertexSize= memSize;
00668         return true;
00669     }
00670     else
00671         return false;
00672 }
00673 
00674 
00675 // ***************************************************************************
00676 void        CVertexBufferHardGLATI::initGL(CVertexArrayRangeATI *var, void *vertexPtr)
00677 {
00678     H_AUTO_OGL(CVertexBufferHardGLATI_initGL)
00679     _VertexArrayRange= var;
00680     _VertexPtr= vertexPtr;
00681 }
00682 
00683 
00684 // ***************************************************************************
00685 void        *CVertexBufferHardGLATI::lock()
00686 {
00687     H_AUTO_OGL(CVertexBufferHardGLATI_lock)
00688     // return directly the mirror one. => client will write into RAM.
00689     return _RAMMirrorVertexPtr;
00690 }
00691 
00692 
00693 // ***************************************************************************
00694 void        CVertexBufferHardGLATI::unlock()
00695 {
00696     H_AUTO_OGL(CVertexBufferHardGLATI_unlock)
00697     // Copy All mirror into the ATI Vertex Object
00698     nglUpdateObjectBufferATI(getATIVertexObjectId(), (ptrdiff_t)_VertexPtr - NL3D_DRV_ATI_FAKE_MEM_START,
00699         _RAMMirrorVertexSize, _RAMMirrorVertexPtr, GL_PRESERVE_ATI);
00700 }
00701 
00702 
00703 // ***************************************************************************
00704 void        CVertexBufferHardGLATI::unlock(uint start, uint end)
00705 {
00706     H_AUTO_OGL(CVertexBufferHardGLATI_unlosk_start_end)
00707     unlock();
00708     // clamp end.
00709     if(end>VB->getNumVertices()*VB->getVertexSize())
00710         end=VB->getNumVertices()*VB->getVertexSize();
00711 
00712     // verify bound.
00713     //if(start>=end)
00714     //  return;
00715     if (start == 0 && end == 0)
00716     {
00717         end = VB->getVertexSize() * VB->getNumVertices();
00718     }
00719 
00720     // Copy a subset of the mirror into the ATI Vertex Object
00721     uint    size= end-start;
00722     uint    srcOffStart= start;
00723     uint    dstOffStart= ((ptrdiff_t)_VertexPtr - NL3D_DRV_ATI_FAKE_MEM_START) + srcOffStart;
00724     // copy.
00725     nglUpdateObjectBufferATI(getATIVertexObjectId(), dstOffStart,
00726         size, (uint8*)_RAMMirrorVertexPtr + srcOffStart, GL_PRESERVE_ATI);
00727 }
00728 
00729 
00730 // ***************************************************************************
00731 void        *CVertexBufferHardGLATI::getPointer()
00732 {
00733     H_AUTO_OGL(CVertexBufferHardGLATI_getPointer)
00734     return (uint8 *) _VertexPtr - NL3D_DRV_ATI_FAKE_MEM_START;
00735 }
00736 
00737 // ***************************************************************************
00738 void            CVertexBufferHardGLATI::enable()
00739 {
00740     H_AUTO_OGL(CVertexBufferHardGLATI_enable)
00741     if(_Driver->_CurrentVertexBufferHard != this)
00742     {
00743         nlassert(_VertexArrayRange);
00744         _VertexArrayRange->enable();
00745         _Driver->_CurrentVertexBufferHard= this;
00746     }
00747 }
00748 
00749 
00750 // ***************************************************************************
00751 void            CVertexBufferHardGLATI::disable()
00752 {
00753     H_AUTO_OGL(CVertexBufferHardGLATI_disbale)
00754     if(_Driver->_CurrentVertexBufferHard != NULL)
00755     {
00756         nlassert(_VertexArrayRange);
00757         _VertexArrayRange->disable();
00758         _Driver->_CurrentVertexBufferHard= NULL;
00759     }
00760 }
00761 
00762 // ***************************************************************************
00763 void            CVertexBufferHardGLATI::lockHintStatic(bool /* staticLock */)
00764 {
00765     H_AUTO_OGL(CVertexBufferHardGLATI_lockHintStatic)
00766     // no op.
00767 }
00768 
00769 // ***************************************************************************
00770 
00771 void CVertexBufferHardGLATI::setupVBInfos(CVertexBufferInfo &vb)
00772 {
00773     H_AUTO_OGL(CVertexBufferHardGLATI_setupVBInfos)
00774     vb.VBMode = CVertexBufferInfo::HwATI;
00775     vb.VertexObjectId = getATIVertexObjectId();
00776 }
00777 
00778 // ***************************************************************************
00779 
00780 // ***************************************************************************
00781 // ***************************************************************************
00782 // ***************************************************************************
00783 //
00784 // ATI implementation, version 2 using the map object buffer extension
00785 //
00786 // ***************************************************************************
00787 // ***************************************************************************
00788 // ***************************************************************************
00789 
00790 
00791 // ***************************************************************************
00792 // CVertexArrayRangeMapObjectATI
00793 // ***************************************************************************
00794 
00795 
00796 // ***************************************************************************
00797 CVertexArrayRangeMapObjectATI::CVertexArrayRangeMapObjectATI(CDriverGL *drv) : IVertexArrayRange(drv),
00798                                                                                _VBType(CVertexBuffer::AGPPreferred),
00799                                                                                _SizeAllocated(0)
00800 {
00801     H_AUTO_OGL(CVertexArrayRangeMapObjectATI_CVertexArrayRangeMapObjectATI)
00802 }
00803 
00804 // ***************************************************************************
00805 bool CVertexArrayRangeMapObjectATI::allocate(uint32 size, CVertexBuffer::TPreferredMemory vbType)
00806 {
00807     H_AUTO_OGL(CVertexArrayRangeMapObjectATI_allocate)
00808     // We don't manage memory ourselves, but test if there's enough room anyway
00809     GLuint vertexObjectId;
00810     switch(vbType)
00811     {
00812         case CVertexBuffer::AGPPreferred:
00813             vertexObjectId = nglNewObjectBufferATI(size, NULL, GL_DYNAMIC_ATI);
00814             break;
00815         case CVertexBuffer::StaticPreferred:
00816             if (_Driver->getStaticMemoryToVRAM())
00817                 vertexObjectId = nglNewObjectBufferATI(size, NULL, GL_STATIC_ATI);
00818             else
00819                 vertexObjectId = nglNewObjectBufferATI(size, NULL, GL_DYNAMIC_ATI);
00820             break;
00821         default:
00822             vertexObjectId = 0;
00823             break;
00824     }
00825     if (vertexObjectId)
00826     {
00827         // free the object
00828         nglDeleteObjectBufferATI(vertexObjectId);
00829         //
00830         _SizeAllocated = size;
00831         _VBType = vbType;
00832         return true;
00833     }
00834     return false;
00835 }
00836 
00837 // ***************************************************************************
00838 void CVertexArrayRangeMapObjectATI::free()
00839 {
00840     H_AUTO_OGL(CVertexArrayRangeMapObjectATI_free)
00841     _SizeAllocated = 0;
00842 }
00843 
00844 // ***************************************************************************
00845 IVertexBufferHardGL *CVertexArrayRangeMapObjectATI::createVBHardGL(uint size, CVertexBuffer *vb)
00846 {
00847     H_AUTO_OGL(CVertexArrayRangeMapObjectATI_createVBHardGL)
00848     // create a ATI VBHard
00849     CVertexBufferHardGLMapObjectATI *newVbHard= new CVertexBufferHardGLMapObjectATI(_Driver, vb);
00850     uint vertexObjectId;
00851     // just allocate a new buffer..
00852     switch(_VBType)
00853     {
00854         case CVertexBuffer::AGPPreferred:
00855             vertexObjectId = nglNewObjectBufferATI(size, NULL, GL_DYNAMIC_ATI);
00856             break;
00857         case CVertexBuffer::StaticPreferred:
00858             if (_Driver->getStaticMemoryToVRAM())
00859                 vertexObjectId = nglNewObjectBufferATI(size, NULL, GL_STATIC_ATI);
00860             else
00861                 vertexObjectId = nglNewObjectBufferATI(size, NULL, GL_DYNAMIC_ATI);
00862             break;
00863         default:
00864             vertexObjectId = 0;
00865             break;
00866     };
00867     // init the allocator, if success
00868     if( nglIsObjectBufferATI(vertexObjectId) )
00869     {
00870         newVbHard->initGL(this, vertexObjectId);
00871         return newVbHard;
00872     }
00873     else
00874     {
00875         delete newVbHard;
00876         return NULL;
00877     }
00878 }
00879 
00880 // ***************************************************************************
00881 void CVertexArrayRangeMapObjectATI::enable()
00882 {
00883     H_AUTO_OGL(CVertexArrayRangeMapObjectATI_enable)
00884 }
00885 
00886 // ***************************************************************************
00887 void CVertexArrayRangeMapObjectATI::disable()
00888 {
00889     H_AUTO_OGL(CVertexArrayRangeMapObjectATI_disbale)
00890 }
00891 
00892 
00893 
00894 // ***************************************************************************
00895 // CVertexBufferHardGLMapObjectATI
00896 // ***************************************************************************
00897 
00898 // ***************************************************************************
00899 CVertexBufferHardGLMapObjectATI::CVertexBufferHardGLMapObjectATI(CDriverGL *drv, CVertexBuffer *vb) :  IVertexBufferHardGL(drv, vb),
00900                                                                                     _VertexPtr(NULL),
00901                                                                                     _VertexArrayRange(NULL),
00902                                                                                     _VertexObjectId(0)
00903 {
00904     H_AUTO_OGL(CVertexBufferHardGLMapObjectATI_CVertexBufferHardGLMapObjectATI)
00905     // Flag our type
00906     VBType = ATIMapObjectVB;
00907 }
00908 
00909 // ***************************************************************************
00910 CVertexBufferHardGLMapObjectATI::~CVertexBufferHardGLMapObjectATI()
00911 {
00912     H_AUTO_OGL(CVertexBufferHardGLMapObjectATI_CVertexBufferHardGLMapObjectATIDtor)
00913     if (_VertexObjectId) nglDeleteObjectBufferATI(_VertexObjectId);
00914     #ifdef NL_DEBUG
00915         if (_VertexPtr)
00916         {
00917             _VertexArrayRange->_MappedVBList.erase(_IteratorInMappedVBList);
00918         }
00919     #endif
00920     if (_VertexArrayRange)
00921     {
00922         if (_Invalid)
00923         {
00924             if (VB->getLocation() != CVertexBuffer::NotResident)
00925             {
00926                 // when the vb is put in tthe NotResident state, it is removed from that list
00927                 _VertexArrayRange->_LostVBList.erase(_IteratorInLostVBList);
00928             }
00929         }
00930     }
00931 }
00932 
00933 // ***************************************************************************
00934 void *CVertexBufferHardGLMapObjectATI::lock()
00935 {
00936     H_AUTO_OGL(CVertexBufferHardGLMapObjectATI_lock)
00937     if (_VertexPtr) return _VertexPtr; // already locked
00938     if (_Invalid)
00939     {
00940         if (VB->getLocation() != CVertexBuffer::NotResident)
00941         {
00942             nlassert(!_DummyVB.empty());
00943             return &_DummyVB[0];
00944         }
00945         // recreate a vb
00946         const uint size = VB->getNumVertices() * VB->getVertexSize();
00947         nlassert(!_VertexObjectId);
00948         switch(_VertexArrayRange->getVBType())
00949         {
00950             case CVertexBuffer::AGPPreferred:
00951                 _VertexObjectId = nglNewObjectBufferATI(size, NULL, GL_DYNAMIC_ATI);
00952                 break;
00953             case CVertexBuffer::StaticPreferred:
00954                 if (_Driver->getStaticMemoryToVRAM())
00955                     _VertexObjectId = nglNewObjectBufferATI(size, NULL, GL_STATIC_ATI);
00956                 else
00957                     _VertexObjectId = nglNewObjectBufferATI(size, NULL, GL_DYNAMIC_ATI);
00958                 break;
00959             default:
00960                 break;
00961         };
00962         if (!_VertexObjectId)
00963         {
00964             _Driver->incrementResetCounter();
00965             nlassert(!_DummyVB.empty());
00966             return &_DummyVB[0];
00967         }
00968         NLMISC::contReset(_DummyVB); // free vector memory for real
00969         nlassert(_VertexObjectId);
00970         _Invalid = false;
00971         _VertexArrayRange->_LostVBList.erase(_IteratorInLostVBList);
00972         // continue to standard mapping code below ..
00973     }
00974     if (!_VertexObjectId) return NULL;
00975     _VertexPtr = nglMapObjectBufferATI(_VertexObjectId);
00976     if (!_VertexPtr)
00977     {
00978         nglUnmapObjectBufferATI(_VertexObjectId);
00979         nlassert(nglIsObjectBufferATI(_VertexObjectId));
00980         invalidate();
00981         return &_DummyVB[0];
00982     }
00983     #ifdef NL_DEBUG
00984         _VertexArrayRange->_MappedVBList.push_front(this);
00985         _IteratorInMappedVBList = _VertexArrayRange->_MappedVBList.begin();
00986     #endif
00987     return _VertexPtr;
00988 
00989 
00990 }
00991 
00992 // ***************************************************************************
00993 void CVertexBufferHardGLMapObjectATI::invalidate()
00994 {
00995     H_AUTO_OGL(CVertexBufferHardGLMapObjectATI_invalidate)
00996     nlassert(!_Invalid);
00997     // Buffer is lost (maybe there was a alt-tab or fullscrren / windowed change)
00998     // Buffer is deleted at end of frame only
00999     _Invalid = true;
01000     _Driver->incrementResetCounter();
01001     _DummyVB.resize(VB->getNumVertices() * VB->getVertexSize(), 0);
01002     // insert in lost vb list
01003     _VertexArrayRange->_LostVBList.push_front(this);
01004     _IteratorInLostVBList = _VertexArrayRange->_LostVBList.begin();
01005 }
01006 
01007 // ***************************************************************************
01008 void CVertexBufferHardGLMapObjectATI::unlock()
01009 {
01010     H_AUTO_OGL(CVertexBufferHardGLMapObjectATI_unlock)
01011     #ifdef NL_DEBUG
01012         if (_VertexPtr)
01013         {
01014             _VertexArrayRange->_MappedVBList.erase(_IteratorInMappedVBList);
01015         }
01016     #endif
01017     _VertexPtr = NULL;
01018     if (_Invalid) return;
01019     if (!_VertexObjectId) return;
01020     #ifdef NL_DEBUG
01021         _Unmapping = true;
01022     #endif
01023     nglUnmapObjectBufferATI(_VertexObjectId);
01024     #ifdef NL_DEBUG
01025         _Unmapping = false;
01026     #endif
01027 }
01028 
01029 // ***************************************************************************
01030 void        *CVertexBufferHardGLMapObjectATI::getPointer()
01031 {
01032     H_AUTO_OGL(CVertexBufferHardGLMapObjectATI_getPointer)
01033     return _VertexPtr;
01034 }
01035 
01036 // ***************************************************************************
01037 void CVertexBufferHardGLMapObjectATI::unlock(uint /* start */,uint /* endVert */)
01038 {
01039     H_AUTO_OGL(CVertexBufferHardGLMapObjectATI_unlock)
01040     unlock(); // can't do a lock on a range of the vb..
01041 }
01042 
01043 // ***************************************************************************
01044 void CVertexBufferHardGLMapObjectATI::enable()
01045 {
01046     H_AUTO_OGL(CVertexBufferHardGLMapObjectATI_enable)
01047     if(_Driver->_CurrentVertexBufferHard != this)
01048     {
01049         /* nlassert(_VertexArrayRange);
01050         _VertexArrayRange->enable(); */
01051         _Driver->_CurrentVertexBufferHard= this;
01052     }
01053 }
01054 
01055 // ***************************************************************************
01056 void CVertexBufferHardGLMapObjectATI::disable()
01057 {
01058     H_AUTO_OGL(CVertexBufferHardGLMapObjectATI_disable)
01059     if(_Driver->_CurrentVertexBufferHard != NULL)
01060     {
01061         /* nlassert(_VertexArrayRange);
01062         _VertexArrayRange->disable(); */
01063         _Driver->_CurrentVertexBufferHard= NULL;
01064     }
01065 }
01066 
01067 // ***************************************************************************
01068 void CVertexBufferHardGLMapObjectATI::initGL(CVertexArrayRangeMapObjectATI *var, uint vertexObjectID)
01069 {
01070     H_AUTO_OGL(CVertexBufferHardGLMapObjectATI_initGL)
01071     _VertexArrayRange = var;
01072     _VertexObjectId = vertexObjectID;
01073 }
01074 
01075 // ***************************************************************************
01076 void            CVertexBufferHardGLMapObjectATI::lockHintStatic(bool /* staticLock */)
01077 {
01078     H_AUTO_OGL(CVertexBufferHardGLMapObjectATI_lockHintStatix)
01079     // no op.
01080 }
01081 
01082 // ***************************************************************************
01083 void CVertexBufferHardGLMapObjectATI::setupVBInfos(CVertexBufferInfo &vb)
01084 {
01085     H_AUTO_OGL(CVertexBufferHardGLMapObjectATI_setupVBInfos)
01086     vb.VBMode = CVertexBufferInfo::HwATI;
01087     vb.VertexObjectId = getATIVertexObjectId();
01088 }
01089 
01090 // ***************************************************************************
01091 void CVertexArrayRangeMapObjectATI::updateLostBuffers()
01092 {
01093     H_AUTO_OGL(CVertexArrayRangeMapObjectATI_updateLostBuffers)
01094     // Put all vb that have been lost in the NotResident state so that they will be recomputed
01095     // We do this only if the app is active, because if vb were lost, it is likely that there are no resources available.
01096     nlassert(_Driver);
01097     if (_Driver->isWndActive())
01098     {
01099         for(std::list<CVertexBufferHardGLMapObjectATI *>::iterator it = _LostVBList.begin(); it != _LostVBList.end(); ++it)
01100         {
01101             nlassert((*it)->_VertexObjectId);
01102             nlassert(nglIsObjectBufferATI((*it)->_VertexObjectId));
01103             nglDeleteObjectBufferATI((*it)->_VertexObjectId);
01104             (*it)->_VertexObjectId = 0;
01105             (*it)->VB->setLocation(CVertexBuffer::NotResident);
01106         }
01107         _LostVBList.clear();
01108     }
01109 }
01110 // ***************************************************************************
01111 #ifdef NL_DEBUG
01112     void CVertexArrayRangeMapObjectATI::dumpMappedBuffers()
01113     {
01114         nlwarning("*****************************************************");
01115         nlwarning("Mapped buffers :");
01116         for(std::list<CVertexBufferHardGLMapObjectATI *>::iterator it = _MappedVBList.begin(); it != _MappedVBList.end(); ++it)
01117         {
01118             CVertexBufferHardGLMapObjectATI &vbati = **it;
01119             nlwarning("Buffer id = %u, size = %u, address = %p", vbati._VertexObjectId, vbati.VB->getVertexSize() * vbati.VB->getNumVertices(), vbati.getPointer());
01120         }
01121     }
01122 #endif
01123 
01124 
01125 
01126 
01127 // ***************************************************************************
01128 // ***************************************************************************
01129 // ***************************************************************************
01130 // ARB implementation
01131 // ***************************************************************************
01132 // ***************************************************************************
01133 // ***************************************************************************
01134 
01135 
01136 // ***************************************************************************
01137 // CVertexArrayRangeARB
01138 // ***************************************************************************
01139 
01140 
01141 // ***************************************************************************
01142 CVertexArrayRangeARB::CVertexArrayRangeARB(CDriverGL *drv) : IVertexArrayRange(drv),
01143                                                              _VBType(CVertexBuffer::AGPPreferred),
01144                                                              _SizeAllocated(0)
01145 {
01146     H_AUTO_OGL(CVertexArrayRangeARB_CVertexArrayRangeARB)
01147 }
01148 
01149 // ***************************************************************************
01150 bool CVertexArrayRangeARB::allocate(uint32 size, CVertexBuffer::TPreferredMemory vbType)
01151 {
01152     H_AUTO_OGL(CVertexArrayRangeARB_allocate)
01153     nlassert(_SizeAllocated == 0);
01154     /*
01155     // We don't manage memory ourselves, but test if there's enough room anyway
01156     GLuint vertexBufferID;
01157     glGetError();
01158     glGenBuffersARB(1, &vertexBufferID);
01159     if (glGetError() != GL_NO_ERROR) return false;
01160 
01161     switch(vbType)
01162     {
01163         case CVertexBuffer::AGPPreferred:
01164             glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB);
01165         break;
01166         case CVertexBuffer::VRAMPreferred:
01167             glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_STATIC_DRAW_ARB);
01168         break;
01169         default:
01170             nlassert(0);
01171         break;
01172     }
01173 
01174     if (glGetError() != GL_NO_ERROR)
01175     {
01176         glDeleteBuffersARB(1, &vertexBufferID);
01177         return false;
01178     }
01179     glDeleteBuffersARB(1, &vertexBufferID);
01180     */
01181     _SizeAllocated = size;
01182     _VBType = vbType;
01183     return true;
01184 }
01185 
01186 // ***************************************************************************
01187 void CVertexArrayRangeARB::free()
01188 {
01189     H_AUTO_OGL(CVertexArrayRangeARB_free)
01190     _SizeAllocated = 0;
01191 }
01192 
01193 // ***************************************************************************
01194 IVertexBufferHardGL *CVertexArrayRangeARB::createVBHardGL(uint size, CVertexBuffer *vb)
01195 {
01196     H_AUTO_OGL(CVertexArrayRangeARB_createVBHardGL)
01197     if (!_SizeAllocated) return NULL;
01198     // create a ARB VBHard
01199     GLuint vertexBufferID;
01200     glGetError();
01201     nglGenBuffersARB(1, &vertexBufferID);
01202     if (glGetError() != GL_NO_ERROR) return false;
01203     _Driver->_DriverGLStates.forceBindARBVertexBuffer(vertexBufferID);
01204     switch(_VBType)
01205     {
01206         case CVertexBuffer::AGPPreferred:
01207             nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB);
01208             break;
01209         case CVertexBuffer::StaticPreferred:
01210             if (_Driver->getStaticMemoryToVRAM())
01211                 nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_STATIC_DRAW_ARB);
01212             else
01213                 nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB);
01214             break;
01215         default:
01216             nlassert(0);
01217             break;
01218     }
01219     if (glGetError() != GL_NO_ERROR)
01220     {
01221         nglDeleteBuffersARB(1, &vertexBufferID);
01222         return false;
01223     }
01224     CVertexBufferHardARB *newVbHard= new CVertexBufferHardARB(_Driver, vb);
01225     newVbHard->initGL(vertexBufferID, this, _VBType);
01226     _Driver->_DriverGLStates.forceBindARBVertexBuffer(0);
01227     return newVbHard;
01228 }
01229 
01230 // ***************************************************************************
01231 void CVertexArrayRangeARB::enable()
01232 {
01233     H_AUTO_OGL(CVertexArrayRangeARB_enable)
01234     if(_Driver->_CurrentVertexArrayRange != this)
01235     {
01236         _Driver->_CurrentVertexArrayRange= this;
01237     }
01238 }
01239 
01240 // ***************************************************************************
01241 void CVertexArrayRangeARB::disable()
01242 {
01243     H_AUTO_OGL(CVertexArrayRangeARB_disbale)
01244     if(_Driver->_CurrentVertexBufferHard != NULL)
01245     {
01246         _Driver->_CurrentVertexBufferHard= NULL;
01247     }
01248 }
01249 
01250 // ***************************************************************************
01251 void CVertexArrayRangeARB::updateLostBuffers()
01252 {
01253     H_AUTO_OGL(CVertexArrayRangeARB_updateLostBuffers)
01254     // Put all vb that have been lost in the NotResident state so that they will be recomputed
01255     // We do this only if the app is active, because if vb were lost, it is likely that there are no resources available.
01256     nlassert(_Driver);
01257     if (_Driver->isWndActive())
01258     {
01259         for(std::list<CVertexBufferHardARB *>::iterator it = _LostVBList.begin(); it != _LostVBList.end(); ++it)
01260         {
01261             nlassert((*it)->_VertexObjectId);
01262             GLuint id = (GLuint) (*it)->_VertexObjectId;
01263             nlassert(nglIsBufferARB(id));
01264             nglDeleteBuffersARB(1, &id);
01265             (*it)->_VertexObjectId = 0;
01266             (*it)->VB->setLocation(CVertexBuffer::NotResident);
01267         }
01268         _LostVBList.clear();
01269     }
01270 }
01271 
01272 
01273 // ***************************************************************************
01274 // CVertexBufferHardARB
01275 // ***************************************************************************
01276 
01277 
01278 // ***************************************************************************
01279 CVertexBufferHardARB::CVertexBufferHardARB(CDriverGL *drv, CVertexBuffer *vb) :  IVertexBufferHardGL(drv, vb),
01280                                                                                  _VertexPtr(NULL),
01281                                                                                 _VertexObjectId(0)
01282 
01283 {
01284     H_AUTO_OGL(CVertexBufferHardARB_CVertexBufferHardARB)
01285     // Flag our type
01286     VBType = ARBVB;
01287     _VertexArrayRange = NULL;
01288     #ifdef NL_DEBUG
01289         _Unmapping = false;
01290     #endif
01291 }
01292 
01293 // ***************************************************************************
01294 CVertexBufferHardARB::~CVertexBufferHardARB()
01295 {
01296     H_AUTO_OGL(CVertexBufferHardARB_CVertexBufferHardARBDtor)
01297     if (_Driver && _VertexObjectId)
01298     {
01299         if (_Driver->_DriverGLStates.getCurrBoundARBVertexBuffer() == _VertexObjectId)
01300         {
01301             _Driver->_DriverGLStates.forceBindARBVertexBuffer(0);
01302         }
01303     }
01304     if (_VertexObjectId)
01305     {
01306         GLuint id = (GLuint) _VertexObjectId;
01307         nlassert(nglIsBufferARB(id));
01308         nglDeleteBuffersARB(1, &id);
01309     }
01310     if (_VertexArrayRange)
01311     {
01312         if (_Invalid)
01313         {
01314             if (VB->getLocation() != CVertexBuffer::NotResident)
01315             {
01316                 // when the vb is put in tthe NotResident state, it is removed from that list
01317                 _VertexArrayRange->_LostVBList.erase(_IteratorInLostVBList);
01318             }
01319         }
01320     }
01321     #ifdef NL_DEBUG
01322         if (_VertexPtr)
01323         {
01324             _VertexArrayRange->_MappedVBList.erase(_IteratorInMappedVBList);
01325         }
01326     #endif
01327 }
01328 
01329 // ***************************************************************************
01330 void *CVertexBufferHardARB::lock()
01331 {
01332     H_AUTO_OGL(CVertexBufferHardARB_lock)
01333     if (_VertexPtr) return _VertexPtr; // already locked
01334     if (_Invalid)
01335     {
01336         if (VB->getLocation() != CVertexBuffer::NotResident)
01337         {
01338             nlassert(!_DummyVB.empty());
01339             return &_DummyVB[0];
01340         }
01341         // recreate a vb
01342         GLuint vertexBufferID;
01343         nglGenBuffersARB(1, &vertexBufferID);
01344         if (glGetError() != GL_NO_ERROR)
01345         {
01346             _Driver->incrementResetCounter();
01347             return &_DummyVB[0];
01348         }
01349         const uint size = VB->getNumVertices() * VB->getVertexSize();
01350         _Driver->_DriverGLStates.forceBindARBVertexBuffer(vertexBufferID);
01351         switch(_MemType)
01352         {
01353             case CVertexBuffer::AGPPreferred:
01354                 nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB);
01355             break;
01356             case CVertexBuffer::StaticPreferred:
01357                 if (_Driver->getStaticMemoryToVRAM())
01358                     nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_STATIC_DRAW_ARB);
01359                 else
01360                     nglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB);
01361             break;
01362             default:
01363                 nlassert(0);
01364             break;
01365         }
01366         if (glGetError() != GL_NO_ERROR)
01367         {
01368             _Driver->incrementResetCounter();
01369             nglDeleteBuffersARB(1, &vertexBufferID);
01370             return &_DummyVB[0];;
01371         }
01372         _VertexObjectId = vertexBufferID;
01373         NLMISC::contReset(_DummyVB); // free vector memory for real
01374         nlassert(_VertexObjectId);
01375         _Invalid = false;
01376         _VertexArrayRange->_LostVBList.erase(_IteratorInLostVBList);
01377         // continue to standard mapping code below ..
01378     }
01379     TTicks  beforeLock = 0;
01380     if(_Driver->_VBHardProfiling)
01381     {
01382         beforeLock= CTime::getPerformanceTime();
01383     }
01384     _Driver->_DriverGLStates.bindARBVertexBuffer(_VertexObjectId);
01385     _VertexPtr = nglMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
01386     if (!_VertexPtr)
01387     {
01388         nglUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
01389         nlassert(nglIsBufferARB((GLuint) _VertexObjectId));
01390         invalidate();
01391         return &_DummyVB[0];
01392     }
01393     #ifdef NL_DEBUG
01394         _VertexArrayRange->_MappedVBList.push_front(this);
01395         _IteratorInMappedVBList = _VertexArrayRange->_MappedVBList.begin();
01396     #endif
01397     _Driver->_DriverGLStates.forceBindARBVertexBuffer(0);
01398     // Lock Profile?
01399     if(_Driver->_VBHardProfiling)
01400     {
01401         TTicks  afterLock;
01402         afterLock= CTime::getPerformanceTime();
01403         _Driver->appendVBHardLockProfile(afterLock-beforeLock, VB);
01404     }
01405     return _VertexPtr;
01406 }
01407 
01408 // ***************************************************************************
01409 void CVertexBufferHardARB::unlock()
01410 {
01411     H_AUTO_OGL(CVertexBufferHardARB_unlock)
01412     _VertexPtr = NULL;
01413     if (_Invalid) return;
01414     if (!_VertexObjectId) return;
01415     TTicks  beforeLock = 0;
01416     if(_Driver->_VBHardProfiling)
01417     {
01418         beforeLock= CTime::getPerformanceTime();
01419     }
01420     _Driver->_DriverGLStates.bindARBVertexBuffer(_VertexObjectId);
01421     // double start = CTime::ticksToSecond(CTime::getPerformanceTime());
01422     #ifdef NL_DEBUG
01423         _Unmapping = true;
01424     #endif
01425     GLboolean unmapOk = nglUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
01426     #ifdef NL_DEBUG
01427         _Unmapping = false;
01428     #endif
01429     // Lock Profile?
01430     if(_Driver->_VBHardProfiling)
01431     {
01432         TTicks  afterLock;
01433         afterLock= CTime::getPerformanceTime();
01434         _Driver->appendVBHardLockProfile(afterLock-beforeLock, VB);
01435     }
01436     #ifdef NL_DEBUG
01437         _VertexArrayRange->_MappedVBList.erase(_IteratorInMappedVBList);
01438     #endif
01439     _Driver->_DriverGLStates.forceBindARBVertexBuffer(0);
01440     if (!unmapOk)
01441     {
01442         invalidate();
01443     }
01444     /* double end = CTime::ticksToSecond(CTime::getPerformanceTime());
01445     nlinfo("3D: Unlock = %f ms", (float) ((end - start) * 1000)); */
01446 }
01447 
01448 // ***************************************************************************
01449 void        *CVertexBufferHardARB::getPointer()
01450 {
01451     H_AUTO_OGL(CVertexBufferHardARB_getPointer)
01452     return _VertexPtr;
01453 }
01454 
01455 // ***************************************************************************
01456 void CVertexBufferHardARB::unlock(uint /* startVert */,uint /* endVert */)
01457 {
01458     H_AUTO_OGL(CVertexBufferHardARB_unlock)
01459     unlock(); // can't do a lock on a range of the vb..
01460 }
01461 
01462 // ***************************************************************************
01463 void CVertexBufferHardARB::enable()
01464 {
01465     H_AUTO_OGL(CVertexBufferHardARB_enable)
01466     if(_Driver->_CurrentVertexBufferHard != this)
01467     {
01468         /* nlassert(_VertexArrayRange);
01469         _VertexArrayRange->enable(); */
01470         _Driver->_CurrentVertexBufferHard= this;
01471     }
01472 }
01473 
01474 // ***************************************************************************
01475 void CVertexBufferHardARB::disable()
01476 {
01477     H_AUTO_OGL(CVertexBufferHardARB_disable)
01478     if(_Driver->_CurrentVertexBufferHard != NULL)
01479     {
01480         /* nlassert(_VertexArrayRange);
01481         _VertexArrayRange->disable(); */
01482         _Driver->_CurrentVertexBufferHard= NULL;
01483     }
01484 }
01485 
01486 // ***************************************************************************
01487 void CVertexBufferHardARB::initGL(uint vertexObjectID, CVertexArrayRangeARB *var, CVertexBuffer::TPreferredMemory memType)
01488 {
01489     H_AUTO_OGL(CVertexBufferHardARB_initGL)
01490     _VertexObjectId = vertexObjectID;
01491     _MemType = memType;
01492     _VertexArrayRange = var;
01493 }
01494 
01495 // ***************************************************************************
01496 void            CVertexBufferHardARB::lockHintStatic(bool /* staticLock */)
01497 {
01498     H_AUTO_OGL(CVertexBufferHardARB_lockHintStatic)
01499     // no op.
01500 }
01501 
01502 // ***************************************************************************
01503 void CVertexBufferHardARB::setupVBInfos(CVertexBufferInfo &vb)
01504 {
01505     H_AUTO_OGL(CVertexBufferHardARB_setupVBInfos)
01506     vb.VBMode = CVertexBufferInfo::HwARB;
01507     vb.VertexObjectId = _VertexObjectId;
01508 }
01509 
01510 // ***************************************************************************
01511 void CVertexBufferHardARB::invalidate()
01512 {
01513     H_AUTO_OGL(CVertexBufferHardARB_invalidate)
01514     nlassert(!_Invalid);
01515     // Buffer is lost (maybe there was a alt-tab or fullscrren / windowed change)
01516     // Buffer is deleted at end of frame only
01517     _Invalid = true;
01518     _Driver->incrementResetCounter();
01519     _DummyVB.resize(VB->getNumVertices() * VB->getVertexSize(), 0);
01520     // insert in lost vb list
01521     _VertexArrayRange->_LostVBList.push_front(this);
01522     _IteratorInLostVBList = _VertexArrayRange->_LostVBList.begin();
01523 }
01524 
01525 // ***************************************************************************
01526 #ifdef NL_DEBUG
01527     void CVertexArrayRangeARB::dumpMappedBuffers()
01528     {
01529         nlwarning("*****************************************************");
01530         nlwarning("Mapped buffers :");
01531         for(std::list<CVertexBufferHardARB *>::iterator it = _MappedVBList.begin(); it != _MappedVBList.end(); ++it)
01532         {
01533             CVertexBufferHardARB &vbarb = **it;
01534             nlwarning("Buffer id = %u, size = %u, address = %p", vbarb._VertexObjectId, vbarb.VB->getVertexSize() * vbarb.VB->getNumVertices(), vbarb.getPointer());
01535         }
01536     }
01537 #endif
01538 
01539 
01540 }
01541 

Generated on Thu Jan 7 08:26:26 2010 for NeL by  doxygen 1.6.1