driver_opengl_vertex.cpp

Go to the documentation of this file.
00001 
00006 /* Copyright, 2000 Nevrax Ltd.
00007  *
00008  * This file is part of NEVRAX NEL.
00009  * NEVRAX NEL is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2, or (at your option)
00012  * any later version.
00013 
00014  * NEVRAX NEL is distributed in the hope that it will be useful, but
00015  * WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00017  * General Public License for more details.
00018 
00019  * You should have received a copy of the GNU General Public License
00020  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00021  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00022  * MA 02111-1307, USA.
00023  */
00024 
00025 #include "stdopengl.h"
00026 
00027 #include "driver_opengl.h"
00028 #include "nel/3d/index_buffer.h"
00029 #include "driver_opengl_vertex_buffer_hard.h"
00030 
00031 
00032 
00033 
00034 using namespace std;
00035 using namespace NLMISC;
00036 
00037 
00038 
00039 
00040 // ***************************************************************************
00041 // Flags for software vertex skinning.
00042 #define NL3D_DRV_SOFTSKIN_VNEEDCOMPUTE  3
00043 #define NL3D_DRV_SOFTSKIN_VMUSTCOMPUTE  1
00044 #define NL3D_DRV_SOFTSKIN_VCOMPUTED     0
00045 // 3 means "vertex may need compute".
00046 // 1 means "Primitive say vertex must be computed".
00047 // 0 means "vertex is computed".
00048 
00049 
00050 // 500K min.
00051 #define NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE       (512*1024)
00052 
00053 
00054 
00055 
00056 
00057 namespace NL3D
00058 {
00059 
00060 
00061 
00062 
00063 
00064 
00065 // ***************************************************************************
00066 
00067 CVBDrvInfosGL::CVBDrvInfosGL(CDriverGL *drv, ItVBDrvInfoPtrList it, CVertexBuffer *vb) : IVBDrvInfos(drv, it, vb)
00068 {
00069     H_AUTO_OGL(CVBDrvInfosGL_CVBDrvInfosGL)
00070     _DriverGL = drv;
00071     _VBHard = NULL;
00072     _SystemMemory = NULL;
00073 }
00074 
00075 // ***************************************************************************
00076 
00077 CVBDrvInfosGL::~CVBDrvInfosGL()
00078 {
00079     H_AUTO_OGL(CVBDrvInfosGL_CVBDrvInfosGLDtor)
00080     // Restaure non resident memory
00081     if (VertexBufferPtr)
00082     {
00083         VertexBufferPtr->setLocation(CVertexBuffer::NotResident);
00084         VertexBufferPtr = NULL;
00085     }
00086 
00087     if (_VBHard)
00088     {
00089         _VBHard->disable();
00090         _DriverGL->_VertexBufferHardSet.erase(_VBHard);
00091     }
00092     if (_SystemMemory)
00093     {
00094         delete [] _SystemMemory;
00095     }
00096     _SystemMemory = NULL;
00097     _VBHard = NULL;
00098 }
00099 
00100 // ***************************************************************************
00101 uint8 *CVBDrvInfosGL::lock (uint /* first */, uint /* last */, bool /* readOnly */)
00102 {
00103     H_AUTO_OGL(CVBDrvInfosGL_lock)
00104     if (_VBHard)
00105     {
00106         return (uint8*)_VBHard->lock ();
00107     }
00108     else
00109     {
00110         // Should be a system memory
00111         nlassert (_SystemMemory);
00112         return _SystemMemory;
00113     }
00114 }
00115 
00116 // ***************************************************************************
00117 void CVBDrvInfosGL::unlock (uint first, uint last)
00118 {
00119     H_AUTO_OGL(CVBDrvInfosGL_unlock)
00120     if (_VBHard)
00121     {
00122         _VBHard->unlock(first, last);
00123     }
00124     else
00125     {
00126         // Should be a system memory
00127         nlassert (_SystemMemory);
00128     }
00129 }
00130 
00131 // ***************************************************************************
00132 bool CDriverGL::setupVertexBuffer(CVertexBuffer& VB)
00133 {
00134     H_AUTO_OGL(CDriverGL_setupVertexBuffer)
00135     // 2. If necessary, do modifications.
00136     //==================================
00137     const bool touched = (VB.getTouchFlags() & (CVertexBuffer::TouchedReserve|CVertexBuffer::TouchedVertexFormat)) != 0;
00138     if( touched || (VB.DrvInfos == NULL))
00139     {
00140         // delete first
00141         if(VB.DrvInfos)
00142             delete VB.DrvInfos;
00143         VB.DrvInfos = NULL;
00144 
00145         // create only if some vertices
00146         if(VB.getNumVertices())
00147         {
00148             // 1. Retrieve/Create driver shader.
00149             //==================================
00150             // insert into driver list. (so it is deleted when driver is deleted).
00151             ItVBDrvInfoPtrList  it= _VBDrvInfos.insert(_VBDrvInfos.end(), NULL);
00152             // create and set iterator, for future deletion.
00153             CVBDrvInfosGL *info = new CVBDrvInfosGL(this, it, &VB);
00154             *it= VB.DrvInfos = info;
00155 
00156             // Preferred memory
00157             CVertexBuffer::TPreferredMemory preferred = VB.getPreferredMemory ();
00158             if ((preferred == CVertexBuffer::RAMVolatile) || (preferred == CVertexBuffer::AGPVolatile))
00159                 preferred = CVertexBuffer::RAMPreferred;
00160             const uint size = VB.capacity()*VB.getVertexSize();
00161             uint preferredMemory = _Extensions.DisableHardwareVertexArrayAGP ? CVertexBuffer::RAMPreferred : preferred;
00162             while (preferredMemory != CVertexBuffer::RAMPreferred)
00163             {
00164                 // Vertex buffer hard
00165                 info->_VBHard = createVertexBufferHard(size, VB.capacity(), (CVertexBuffer::TPreferredMemory)preferredMemory, &VB);
00166                 if (info->_VBHard)
00167                     break;
00168                 preferredMemory--;
00169             }
00170 
00171             // No memory found ? Use system memory
00172             if (info->_VBHard == NULL)
00173             {
00174                 nlassert (info->_SystemMemory == NULL);
00175                 info->_SystemMemory = new uint8[size];
00176             }
00177 
00178             // Upload the data
00179             VB.setLocation ((CVertexBuffer::TLocation)preferredMemory);
00180         }
00181     }
00182 
00183     return true;
00184 }
00185 
00186 
00187 // ***************************************************************************
00188 bool        CDriverGL::activeVertexBuffer(CVertexBuffer& VB)
00189 {
00190     H_AUTO_OGL(CDriverGL_activeVertexBuffer)
00191     // NB: must duplicate changes in activeVertexBufferHard()
00192     uint32  flags;
00193 
00194     // In any case, we'll erase any special vertex setup for Lightmap Material
00195     _LastVertexSetupIsLightMap= false;
00196 
00197     // setup
00198     if (!setupVertexBuffer(VB))
00199         return false;
00200 
00201     if (VB.getNumVertices()==0)
00202         return true;
00203 
00204     // Fill the buffer if in local memory
00205     VB.fillBuffer ();
00206 
00207     // Get VB flags, to setup matrixes and arrays.
00208     flags=VB.getVertexFormat();
00209 
00210 
00211     // 2. Setup Arrays.
00212     //===================
00213     // For MultiPass Material.
00214     CVertexBufferInfo::TVBMode lastVBMode = _LastVB.VBMode;
00215     CVBDrvInfosGL       *info= safe_cast<CVBDrvInfosGL*>((IVBDrvInfos*)VB.DrvInfos);
00216     if (!info->_VBHard ||  (info->_VBHard && !info->_VBHard->isInvalid()))
00217     {
00218         _LastVB.setupVertexBuffer(VB);
00219         if (lastVBMode == CVertexBufferInfo::HwARB && _LastVB.VBMode != CVertexBufferInfo::HwARB)
00220         {
00221             _DriverGLStates.bindARBVertexBuffer(0); // unbind ARB vertex buffer
00222         }
00223     }
00224     if (info->_VBHard == NULL)
00225     {
00226         // Fence mgt.
00227         fenceOnCurVBHardIfNeeded(NULL);
00228 
00229         // Disable the current vertexBufferHard if setuped.
00230         if(_CurrentVertexBufferHard)
00231             _CurrentVertexBufferHard->disable();
00232     }
00233     else
00234     {
00235         // 2. Setup Arrays.
00236         //===================
00237 
00238         // Fence mgt.
00239         fenceOnCurVBHardIfNeeded(info->_VBHard);
00240 
00241         // Enable the vertexArrayRange of this array.
00242         info->_VBHard->enable();
00243     }
00244     if (!info->_VBHard ||  (info->_VBHard && !info->_VBHard->isInvalid()))
00245     {
00246         setupGlArrays(_LastVB);
00247     }
00248     return true;
00249 }
00250 
00251 // ***************************************************************************
00252 bool CDriverGL::activeIndexBuffer(CIndexBuffer& IB)
00253 {
00254     H_AUTO_OGL(CDriverGL_activeIndexBuffer)
00255     _LastIB.setupIndexBuffer(IB);
00256     return true;
00257 }
00258 
00259 // ***************************************************************************
00260 
00261 bool CDriverGL::renderLines(CMaterial& mat, uint32 firstIndex, uint32 nlines)
00262 {
00263     H_AUTO_OGL(CDriverGL_renderLines)
00264     // update matrix and Light in OpenGL if needed
00265     refreshRenderSetup();
00266 
00267     // setup material
00268     if ( !setupMaterial(mat) || _LastIB._Values == NULL )
00269         return false;
00270 
00271     if (_CurrentVertexBufferHard && _CurrentVertexBufferHard->isInvalid()) return true;
00272     // render primitives.
00273     //==============================
00274     // start multipass.
00275     uint    nPass;
00276     nPass= beginMultiPass();
00277     // draw all passes.
00278     for(uint pass=0;pass<nPass; pass++)
00279     {
00280         // setup the pass.
00281         setupPass(pass);
00282         // draw the primitives.
00283         if(nlines)
00284         {
00285             if (_LastIB._Format == CIndexBuffer::Indices16)
00286             {
00287                 glDrawElements(GL_LINES,2*nlines,GL_UNSIGNED_SHORT,((uint16 *) _LastIB._Values)+firstIndex);
00288             }
00289             else
00290             {
00291                 nlassert(_LastIB._Format == CIndexBuffer::Indices32);
00292                 glDrawElements(GL_LINES,2*nlines,GL_UNSIGNED_INT,((uint32 *) _LastIB._Values)+firstIndex);
00293             }
00294         }
00295     }
00296     // end multipass.
00297     endMultiPass();
00298 
00299 
00300     // Profiling.
00301     _PrimitiveProfileIn.NLines+= nlines;
00302     _PrimitiveProfileOut.NLines+= nlines;
00303 
00304     // We have render some prims. inform the VBHard.
00305     if(_CurrentVertexBufferHard)
00306         _CurrentVertexBufferHard->GPURenderingAfterFence= true;
00307     return true;
00308 }
00309 
00310 // ***************************************************************************
00311 
00312 bool CDriverGL::renderTriangles(CMaterial& mat, uint32 firstIndex, uint32 ntris)
00313 {
00314     H_AUTO_OGL(CDriverGL_renderTriangles)
00315     // update matrix and Light in OpenGL if needed
00316     refreshRenderSetup();
00317     // setup material
00318     if ( !setupMaterial(mat) || _LastIB._Values == NULL )
00319         return false;
00320 
00321     if (_CurrentVertexBufferHard && _CurrentVertexBufferHard->isInvalid()) return true;
00322 
00323     // render primitives.
00324     //==============================
00325     // start multipass.
00326     uint    nPass;
00327 
00328     nPass= beginMultiPass();
00329 
00330     // draw all passes.
00331     for(uint pass=0;pass<nPass; pass++)
00332     {
00333         // setup the pass.
00334         setupPass(pass);
00335 
00336         // draw the primitives.
00337         if(ntris)
00338         {
00339             if (_LastIB._Format == CIndexBuffer::Indices16)
00340             {
00341                 glDrawElements(GL_TRIANGLES,3*ntris,GL_UNSIGNED_SHORT, ((uint16 *) _LastIB._Values)+firstIndex);
00342             }
00343             else
00344             {
00345                 nlassert(_LastIB._Format == CIndexBuffer::Indices32);
00346                 glDrawElements(GL_TRIANGLES,3*ntris,GL_UNSIGNED_INT, ((uint32 *) _LastIB._Values)+firstIndex);
00347             }
00348         }
00349     }
00350     // end multipass.
00351     endMultiPass();
00352 
00353 
00354     // Profiling.
00355     _PrimitiveProfileIn.NTriangles+= ntris;
00356     _PrimitiveProfileOut.NTriangles+= ntris * nPass;
00357 
00358     // We have render some prims. inform the VBHard.
00359     if(_CurrentVertexBufferHard)
00360         _CurrentVertexBufferHard->GPURenderingAfterFence= true;
00361     return true;
00362 }
00363 
00364 // ***************************************************************************
00365 
00366 bool CDriverGL::renderSimpleTriangles(uint32 firstTri, uint32 ntris)
00367 {
00368     H_AUTO_OGL(CDriverGL_renderSimpleTriangles)
00369     nlassert(ntris>0);
00370 
00371     // update matrix and Light in OpenGL if needed
00372     refreshRenderSetup();
00373 
00374 
00375     if (_CurrentVertexBufferHard && _CurrentVertexBufferHard->isInvalid()) return true;
00376     // Don't setup any material here.
00377 
00378     // render primitives.
00379     //==============================
00380     // NO MULTIPASS HERE!!
00381     // draw the primitives. (nb: ntrsi>0).
00382 
00383     if (_LastIB._Format == CIndexBuffer::Indices16)
00384     {
00385         glDrawElements(GL_TRIANGLES,3*ntris,GL_UNSIGNED_SHORT, ((uint16 *) _LastIB._Values)+firstTri);
00386     }
00387     else
00388     {
00389         nlassert(_LastIB._Format == CIndexBuffer::Indices32);
00390         glDrawElements(GL_TRIANGLES,3*ntris,GL_UNSIGNED_INT, ((uint32 *) _LastIB._Values)+firstTri);
00391     }
00392 
00393     // Profiling.
00394     _PrimitiveProfileIn.NTriangles+= ntris;
00395     _PrimitiveProfileOut.NTriangles+= ntris;
00396 
00397     // We have render some prims. inform the VBHard.
00398     if(_CurrentVertexBufferHard)
00399         _CurrentVertexBufferHard->GPURenderingAfterFence= true;
00400     return true;
00401 }
00402 
00403 // ***************************************************************************
00404 
00405 bool CDriverGL::renderRawPoints(CMaterial& mat, uint32 startIndex, uint32 numPoints)
00406 {
00407     H_AUTO_OGL(CDriverGL_renderRawPoints)
00408     // update matrix and Light in OpenGL if needed
00409     refreshRenderSetup();
00410 
00411     // setup material
00412     if ( !setupMaterial(mat) )
00413         return false;
00414 
00415     if (_CurrentVertexBufferHard && _CurrentVertexBufferHard->isInvalid()) return true;
00416     // render primitives.
00417     //==============================
00418     // start multipass.
00419     uint    nPass;
00420     nPass= beginMultiPass();
00421     // draw all passes.
00422     for(uint pass=0;pass<nPass; pass++)
00423     {
00424         // setup the pass.
00425         setupPass(pass);
00426         // draw the primitives.
00427         if(numPoints)
00428             glDrawArrays(GL_POINTS, startIndex, numPoints);
00429     }
00430     // end multipass.
00431     endMultiPass();
00432 
00433 
00434     // Profiling.
00435     _PrimitiveProfileIn.NPoints+= numPoints;
00436     _PrimitiveProfileOut.NPoints+= numPoints * nPass;
00437 
00438     // We have render some prims. inform the VBHard.
00439     if(_CurrentVertexBufferHard)
00440         _CurrentVertexBufferHard->GPURenderingAfterFence= true;
00441     return true;
00442 }
00443 
00444 // ***************************************************************************
00445 
00446 bool CDriverGL::renderRawLines(CMaterial& mat, uint32 startIndex, uint32 numLines)
00447 {
00448     H_AUTO_OGL(CDriverGL_renderRawLines)
00449     // update matrix and Light in OpenGL if needed
00450     refreshRenderSetup();
00451 
00452     // setup material
00453     if ( !setupMaterial(mat) )
00454         return false;
00455 
00456     if (_CurrentVertexBufferHard && _CurrentVertexBufferHard->isInvalid()) return true;
00457     // render primitives.
00458     //==============================
00459     // start multipass.
00460     uint    nPass;
00461     nPass= beginMultiPass();
00462     // draw all passes.
00463     for(uint pass=0;pass<nPass; pass++)
00464     {
00465         // setup the pass.
00466         setupPass(pass);
00467         // draw the primitives.
00468         if(numLines)
00469             glDrawArrays(GL_LINES, startIndex << 1, numLines << 1);
00470     }
00471     // end multipass.
00472     endMultiPass();
00473 
00474 
00475     // Profiling.
00476     _PrimitiveProfileIn.NLines  += numLines ;
00477     _PrimitiveProfileOut.NLines += numLines  * nPass;
00478 
00479     // We have render some prims. inform the VBHard.
00480     if(_CurrentVertexBufferHard)
00481         _CurrentVertexBufferHard->GPURenderingAfterFence= true;
00482     return true;
00483 }
00484 
00485 // ***************************************************************************
00486 
00487 bool CDriverGL::renderRawTriangles(CMaterial& mat, uint32 startIndex, uint32 numTris)
00488 {
00489     H_AUTO_OGL(CDriverGL_renderRawTriangles)
00490     // update matrix and Light in OpenGL if needed
00491     refreshRenderSetup();
00492 
00493     // setup material
00494     if ( !setupMaterial(mat) )
00495         return false;
00496 
00497     if (_CurrentVertexBufferHard && _CurrentVertexBufferHard->isInvalid()) return true;
00498     // render primitives.
00499     //==============================
00500     // start multipass.
00501     uint    nPass;
00502     nPass= beginMultiPass();
00503     // draw all passes.
00504     for(uint pass=0;pass<nPass; pass++)
00505     {
00506         // setup the pass.
00507         setupPass(pass);
00508         // draw the primitives.
00509         if(numTris)
00510         {
00511             glDrawArrays(GL_TRIANGLES, startIndex*3, numTris*3);
00512         }
00513     }
00514     // end multipass.
00515     endMultiPass();
00516 
00517 
00518     // Profiling.
00519     _PrimitiveProfileIn.NTriangles  += numTris ;
00520     _PrimitiveProfileOut.NTriangles += numTris  * nPass;
00521 
00522     // We have render some prims. inform the VBHard.
00523     if(_CurrentVertexBufferHard)
00524         _CurrentVertexBufferHard->GPURenderingAfterFence= true;
00525     return true;
00526 }
00527 
00528 // ***************************************************************************
00529 
00530 bool CDriverGL::renderRawQuads(CMaterial& mat, uint32 startIndex, uint32 numQuads)
00531 {
00532     H_AUTO_OGL(CDriverGL_renderRawQuads)
00533     if (!numQuads) return true;
00534     // update matrix and Light in OpenGL if needed
00535     refreshRenderSetup();
00536 
00537     // setup material
00538     if ( !setupMaterial(mat) )
00539         return false;
00540 
00541     if (_CurrentVertexBufferHard && _CurrentVertexBufferHard->isInvalid()) return true;
00542 
00543     const uint32 QUAD_BATCH_SIZE = 2048;
00544     static GLshort defaultIndices[QUAD_BATCH_SIZE * 6];
00545     static bool init = false;
00546     if (!init)
00547     {
00548         // setup the base index buffer
00549         for(uint k = 0; k < QUAD_BATCH_SIZE; ++k)
00550         {
00551             // first tri
00552             defaultIndices[k * 6] = (GLshort) (k * 4);
00553             defaultIndices[k * 6 + 1] = (GLshort) (k * 4 + 1);
00554             defaultIndices[k * 6 + 2] = (GLshort) (k * 4 + 2);
00555             // second tri
00556             defaultIndices[k * 6 + 3] = (GLshort) (k * 4);
00557             defaultIndices[k * 6 + 4] = (GLshort) (k * 4 + 2);
00558             defaultIndices[k * 6 + 5] = (GLshort) (k * 4 + 3);
00559 
00560         }
00561         init = true;
00562     }
00563 
00564     // render primitives.
00565     //==============================
00566     // start multipass.
00567     uint    nPass;
00568     nPass= beginMultiPass();
00569     // draw all passes.
00570     for(uint pass=0;pass<nPass; pass++)
00571     {
00572         // setup the pass.
00573         setupPass(pass);
00574 
00575         uint32 currIndex = startIndex;
00576         uint32 numLeftQuads = numQuads;
00577 
00578         // draw first batch of quads using the static setupped array
00579         if (startIndex < QUAD_BATCH_SIZE)
00580         {
00581             // draw first quads (as pair of tri to have guaranteed orientation)
00582             uint numQuadsToDraw = std::min(QUAD_BATCH_SIZE - startIndex, numQuads);
00583             glDrawElements(GL_TRIANGLES, 6 * numQuadsToDraw, GL_UNSIGNED_SHORT, defaultIndices + 6 * startIndex);
00584             numLeftQuads -= numQuadsToDraw;
00585             currIndex += 4 * numQuadsToDraw;
00586         }
00587 
00588         // draw remaining quads
00589         while (numLeftQuads)
00590         {
00591             // TODO : resetting vertex pointer would avoid the need to rebuild indices each times
00592             uint32 numQuadsToDraw = std::min(numLeftQuads, QUAD_BATCH_SIZE);
00593             // draw all quads
00594             if (4 * numQuadsToDraw + currIndex <= (1 << 16))
00595             {
00596                 // indices fits on 16 bits
00597                 GLshort indices[QUAD_BATCH_SIZE * 6];
00598                 GLshort *curr = indices;
00599                 GLshort *end = indices + 6 * numQuadsToDraw;
00600                 uint16 vertexIndex = (uint16) currIndex;
00601                 do
00602                 {
00603                     *curr++ = vertexIndex;
00604                     *curr++ = vertexIndex + 1;
00605                     *curr++ = vertexIndex + 2;
00606                     *curr++ = vertexIndex;
00607                     *curr++ = vertexIndex + 2;
00608                     *curr++ = vertexIndex + 3;
00609                     vertexIndex += 4;
00610                 }
00611                 while(curr != end);
00612                 glDrawElements(GL_TRIANGLES, 6 * numQuadsToDraw, GL_UNSIGNED_SHORT, indices);
00613             }
00614             else
00615             {
00616                 // indices fits on 32 bits
00617                 GLint indices[QUAD_BATCH_SIZE];
00618                 GLint *curr = indices;
00619                 GLint *end = indices + 6 * numQuadsToDraw;
00620                 uint32 vertexIndex = currIndex;
00621                 do
00622                 {
00623                     *curr++ = vertexIndex;
00624                     *curr++ = vertexIndex + 1;
00625                     *curr++ = vertexIndex + 2;
00626                     *curr++ = vertexIndex;
00627                     *curr++ = vertexIndex + 2;
00628                     *curr++ = vertexIndex + 3;
00629                     vertexIndex += 4;
00630                 }
00631                 while(curr != end);
00632                 glDrawElements(GL_TRIANGLES, 6 * numQuadsToDraw, GL_UNSIGNED_INT, indices);
00633             }
00634             numLeftQuads -= numQuadsToDraw;
00635             currIndex += 4 * numQuadsToDraw;
00636         }
00637     }
00638     // end multipass.
00639     endMultiPass();
00640 
00641 
00642     // Profiling.
00643     _PrimitiveProfileIn.NQuads  += numQuads ;
00644     _PrimitiveProfileOut.NQuads += numQuads  * nPass;
00645 
00646     // We have render some prims. inform the VBHard.
00647     if(_CurrentVertexBufferHard)
00648         _CurrentVertexBufferHard->GPURenderingAfterFence= true;
00649     return true;
00650 }
00651 
00652 // ***************************************************************************
00653 
00654 void        CDriverGL::setupUVPtr(uint stage, CVertexBufferInfo &VB, uint uvId)
00655 {
00656     H_AUTO_OGL(CDriverGL_setupUVPtr)
00657     // sould not be called with vertex program Array setuped.
00658     nlassert(!_LastSetupGLArrayVertexProgram);
00659 
00660     _DriverGLStates.clientActiveTextureARB(stage);
00661     if (VB.VertexFormat & (CVertexBuffer::TexCoord0Flag<<uvId))
00662     {
00663         // Check type, if not supported, just ignore
00664         CVertexBuffer::TType uvType = VB.Type[CVertexBuffer::TexCoord0+uvId];
00665         if (uvType == CVertexBuffer::Float2 ||
00666             uvType == CVertexBuffer::Float3)
00667         {
00668             _DriverGLStates.enableTexCoordArray(true);
00669             uint numTexCoord = (uvType == CVertexBuffer::Float2) ? 2 : 3;
00670             // Setup ATI VBHard or std ptr.
00671             switch(VB.VBMode)
00672             {
00673                 case CVertexBufferInfo::HwATI:
00674                     nglArrayObjectATI(GL_TEXTURE_COORD_ARRAY, numTexCoord, GL_FLOAT, VB.VertexSize, VB.VertexObjectId,
00675                                       /*(uint)*/ (ptrdiff_t) VB.ValuePtr[CVertexBuffer::TexCoord0+uvId]);
00676                 break;
00677                 case CVertexBufferInfo::HwARB:
00678                     _DriverGLStates.bindARBVertexBuffer(VB.VertexObjectId);
00679                     // with arb buffers, position is relative to the start of the stream
00680                     glTexCoordPointer(numTexCoord,GL_FLOAT,VB.VertexSize, VB.ValuePtr[CVertexBuffer::TexCoord0+uvId]);
00681                 break;
00682                 case CVertexBufferInfo::SysMem:
00683                 case CVertexBufferInfo::HwNVIDIA:
00684                     glTexCoordPointer(numTexCoord,GL_FLOAT,VB.VertexSize, VB.ValuePtr[CVertexBuffer::TexCoord0+uvId]);
00685                 break;
00686                 default:
00687                     break;
00688             }
00689         }
00690         else
00691         {
00692             _DriverGLStates.enableTexCoordArray(false);
00693         }
00694     }
00695     else
00696         _DriverGLStates.enableTexCoordArray(false);
00697 }
00698 
00699 
00700 // ***************************************************************************
00701 void        CDriverGL::mapTextureStageToUV(uint stage, uint uv)
00702 {
00703     H_AUTO_OGL(CDriverGL_mapTextureStageToUV)
00704     // Just call it for last VertexBuffer setuped.
00705     setupUVPtr(stage, _LastVB, uv);
00706 }
00707 
00708 
00709 
00710 // ***************************************************************************
00711 // ***************************************************************************
00712 // VertexBufferHard
00713 // ***************************************************************************
00714 // ***************************************************************************
00715 
00716 
00717 // ***************************************************************************
00718 bool            CDriverGL::supportVertexBufferHard() const
00719 {
00720     H_AUTO_OGL(CDriverGL_supportVertexBufferHard)
00721     return _SupportVBHard;
00722 }
00723 
00724 // ***************************************************************************
00725 bool            CDriverGL::supportVolatileVertexBuffer() const
00726 {
00727     H_AUTO_OGL(CDriverGL_supportVolatileVertexBuffer)
00728         return false;
00729 }
00730 
00731 
00732 
00733 // ***************************************************************************
00734 bool            CDriverGL::slowUnlockVertexBufferHard() const
00735 {
00736     H_AUTO_OGL(CDriverGL_slowUnlockVertexBufferHard)
00737     return _SlowUnlockVBHard;
00738 }
00739 
00740 
00741 // ***************************************************************************
00742 uint            CDriverGL::getMaxVerticesByVertexBufferHard() const
00743 {
00744     H_AUTO_OGL(CDriverGL_getMaxVerticesByVertexBufferHard)
00745     return _MaxVerticesByVBHard;
00746 }
00747 
00748 
00749 // ***************************************************************************
00750 IVertexBufferHardGL *CDriverGL::createVertexBufferHard(uint size, uint numVertices, CVertexBuffer::TPreferredMemory vbType, CVertexBuffer *vb)
00751 {
00752     H_AUTO_OGL(CDriverGL_createVertexBufferHard)
00753     // choose the VertexArrayRange of good type
00754     IVertexArrayRange   *vertexArrayRange= NULL;
00755     switch(vbType)
00756     {
00757     case CVertexBuffer::AGPPreferred:
00758         vertexArrayRange= _AGPVertexArrayRange;
00759         break;
00760     case CVertexBuffer::StaticPreferred:
00761         if (getStaticMemoryToVRAM())
00762             vertexArrayRange= _VRAMVertexArrayRange;
00763         else
00764             vertexArrayRange= _AGPVertexArrayRange;
00765         break;
00766         default:
00767             break;
00768     };
00769 
00770     // If this one at least created (an extension support it).
00771     if( !vertexArrayRange )
00772         return NULL;
00773     else
00774     {
00775         // check max vertex
00776         if(numVertices > _MaxVerticesByVBHard)
00777             return NULL;
00778 
00779         // Create a CVertexBufferHardGL
00780         IVertexBufferHardGL     *vbHard;
00781         // let the VAR create the vbhard.
00782         vbHard= vertexArrayRange->createVBHardGL(size, vb);
00783         // if fails
00784         if(!vbHard)
00785         {
00786             return NULL;
00787         }
00788         else
00789         {
00790             // insert in list.
00791             return _VertexBufferHardSet.insert(vbHard);
00792         }
00793     }
00794 }
00795 
00796 
00797 // ***************************************************************************
00798 const uint      CDriverGL::NumCoordinatesType[CVertexBuffer::NumType]=
00799 {
00800     1,  // Double1
00801     1,  // Float1
00802     1,  // Short1
00803     2,  // Double2
00804     2,  // Float2
00805     2,  // Short2
00806     3,  // Double3
00807     3,  // Float3
00808     3,  // Short3
00809     4,  // Double4
00810     4,  // Float4
00811     4,  // Short4
00812     4   // UChar4
00813 };
00814 
00815 
00816 // ***************************************************************************
00817 const uint      CDriverGL::GLType[CVertexBuffer::NumType]=
00818 {
00819     GL_DOUBLE,  // Double1
00820     GL_FLOAT,   // Float1
00821     GL_SHORT,   // Short1
00822     GL_DOUBLE,  // Double2
00823     GL_FLOAT,   // Float2
00824     GL_SHORT,   // Short2
00825     GL_DOUBLE,  // Double3
00826     GL_FLOAT,   // Float3
00827     GL_SHORT,   // Short3
00828     GL_DOUBLE,  // Double4
00829     GL_FLOAT,   // Float4
00830     GL_SHORT,   // Short4
00831     GL_UNSIGNED_BYTE    // UChar4
00832 };
00833 
00834 // ***************************************************************************
00835 const bool CDriverGL::GLTypeIsIntegral[CVertexBuffer::NumType] =
00836 {
00837     false,  // Double1
00838     false,  // Float1
00839     true,   // Short1
00840     false,  // Double2
00841     false,  // Float2
00842     true,   // Short2
00843     false,  // Double3
00844     false,  // Float3
00845     true,   // Short3
00846     false,  // Double4
00847     false,  // Float4
00848     true,   // Short4
00849     true    // UChar4
00850 };
00851 
00852 
00853 
00854 // ***************************************************************************
00855 const uint      CDriverGL::GLVertexAttribIndex[CVertexBuffer::NumValue]=
00856 {
00857     0,  // Position
00858     2,  // Normal
00859     8,  // TexCoord0
00860     9,  // TexCoord1
00861     10, // TexCoord2
00862     11, // TexCoord3
00863     12, // TexCoord4
00864     13, // TexCoord5
00865     14, // TexCoord6
00866     15, // TexCoord7
00867     3,  // PrimaryColor
00868     4,  // SecondaryColor
00869     1,  // Weight
00870     6,  // Empty (PaletteSkin)
00871     5,  // Fog
00872     7,  // Empty
00873 };
00874 
00875 
00876 
00877 // ***************************************************************************
00878 void        CDriverGL::setupGlArraysStd(CVertexBufferInfo &vb)
00879 {
00880     H_AUTO_OGL(CDriverGL_setupGlArraysStd)
00881     uint32  flags= vb.VertexFormat;
00882 
00883     if (vb.VBMode == CVertexBufferInfo::HwARB)
00884     {
00885         _DriverGLStates.bindARBVertexBuffer(vb.VertexObjectId);
00886     }
00887 
00888     switch(vb.VBMode)
00889     {
00890         case CVertexBufferInfo::SysMem:
00891         case CVertexBufferInfo::HwNVIDIA:
00892         case CVertexBufferInfo::HwARB:
00893         {
00894 
00895             // setup vertex ptr.
00896             //-----------
00897             uint numVertexCoord = CVertexBuffer::NumComponentsType[vb.Type[CVertexBuffer::Position]];
00898             nlassert (numVertexCoord >= 2);
00899             _DriverGLStates.enableVertexArray(true);
00900             glVertexPointer(numVertexCoord, GL_FLOAT, vb.VertexSize, vb.ValuePtr[CVertexBuffer::Position]);
00901             // setup normal ptr.
00902             //-----------
00903             // Check for normal param in vertex buffer
00904             if (flags & CVertexBuffer::NormalFlag)
00905             {
00906                 // Check type
00907                 nlassert (vb.Type[CVertexBuffer::Normal]==CVertexBuffer::Float3);
00908 
00909                 _DriverGLStates.enableNormalArray(true);
00910                 glNormalPointer(GL_FLOAT, vb.VertexSize, vb.ValuePtr[CVertexBuffer::Normal]);
00911             }
00912             else
00913             {
00914                 _DriverGLStates.enableNormalArray(false);
00915             }
00916             // Setup Color
00917             //-----------
00918             // Check for color param in vertex buffer
00919             if (flags & CVertexBuffer::PrimaryColorFlag)
00920             {
00921                 // Check type
00922                 nlassert (vb.Type[CVertexBuffer::PrimaryColor]==CVertexBuffer::UChar4);
00923                 _DriverGLStates.enableColorArray(true);
00924                 // Setup ATI VBHard or std ptr.
00925                 glColorPointer(4,GL_UNSIGNED_BYTE, vb.VertexSize, vb.ValuePtr[CVertexBuffer::PrimaryColor]);
00926             }
00927             else
00928                 _DriverGLStates.enableColorArray(false);
00929         }
00930         break;
00931         case CVertexBufferInfo::HwATI:
00932         {
00933             // setup vertex ptr.
00934             //-----------
00935             uint numVertexCoord = CVertexBuffer::NumComponentsType[vb.Type[CVertexBuffer::Position]];
00936             nlassert (numVertexCoord >= 2);
00937 
00938             _DriverGLStates.enableVertexArray(true);
00939             nglArrayObjectATI(GL_VERTEX_ARRAY, numVertexCoord, GL_FLOAT, vb.VertexSize, vb.VertexObjectId, (ptrdiff_t)  vb.ValuePtr[CVertexBuffer::Position]);
00940             // setup normal ptr.
00941             //-----------
00942             // Check for normal param in vertex buffer
00943             if (flags & CVertexBuffer::NormalFlag)
00944             {
00945                 // Check type
00946                 nlassert (vb.Type[CVertexBuffer::Normal]==CVertexBuffer::Float3);
00947                 _DriverGLStates.enableNormalArray(true);
00948                     nglArrayObjectATI(GL_NORMAL_ARRAY, 3, GL_FLOAT, vb.VertexSize, vb.VertexObjectId, (ptrdiff_t)  vb.ValuePtr[CVertexBuffer::Normal]);
00949             }
00950             else
00951             {
00952                 _DriverGLStates.enableNormalArray(false);
00953             }
00954 
00955 
00956             // Setup Color
00957             //-----------
00958             // Check for color param in vertex buffer
00959             if (flags & CVertexBuffer::PrimaryColorFlag)
00960             {
00961                 // Check type
00962                 nlassert (vb.Type[CVertexBuffer::PrimaryColor]==CVertexBuffer::UChar4);
00963 
00964                 _DriverGLStates.enableColorArray(true);
00965                 nglArrayObjectATI(GL_COLOR_ARRAY, 4, GL_UNSIGNED_BYTE, vb.VertexSize, vb.VertexObjectId, (ptrdiff_t)  vb.ValuePtr[CVertexBuffer::PrimaryColor]);
00966             }
00967             else
00968                 _DriverGLStates.enableColorArray(false);
00969         }
00970         break;
00971         default:
00972             nlassert(0);
00973         break;
00974     }
00975 
00976     // Setup Uvs
00977     //-----------
00978     // Get the routing
00979     for(uint i=0; i<inlGetNumTextStages(); i++)
00980     {
00981         // normal behavior: each texture has its own UV.
00982         setupUVPtr(i, vb, vb.UVRouting[i]);
00983     }
00984 
00985 
00986 }
00987 
00988 
00989 // ***************************************************************************
00990 void        CDriverGL::toggleGlArraysForNVVertexProgram()
00991 {
00992     H_AUTO_OGL(CDriverGL_toggleGlArraysForNVVertexProgram)
00993     // If change of setup type, must disable olds.
00994     //=======================
00995 
00996     // If last was a VertexProgram setup, and now it is a standard GL array setup.
00997     if( _LastSetupGLArrayVertexProgram && !isVertexProgramEnabled () )
00998     {
00999 
01000         // Disable all VertexAttribs.
01001         for (uint value=0; value<CVertexBuffer::NumValue; value++)
01002         {
01003             // Index
01004             uint glIndex=GLVertexAttribIndex[value];
01005             _DriverGLStates.enableVertexAttribArray(glIndex, false);
01006         }
01007         _DriverGLStates.enableColorArray(false);
01008         _DriverGLStates.enableSecondaryColorArray(false);
01009 
01010         // no more a vertex program setup.
01011         _LastSetupGLArrayVertexProgram= false;
01012     }
01013 
01014     // If last was a standard GL array setup, and now it is a VertexProgram setup.
01015     if( !_LastSetupGLArrayVertexProgram && isVertexProgramEnabled () )
01016     {
01017         // Disable all standards ptrs.
01018         _DriverGLStates.enableVertexArray(false);
01019         _DriverGLStates.enableNormalArray(false);
01020         _DriverGLStates.enableColorArray(false);
01021         for(uint i=0; i<inlGetNumTextStages(); i++)
01022         {
01023             _DriverGLStates.clientActiveTextureARB(i);
01024             _DriverGLStates.enableTexCoordArray(false);
01025         }
01026 
01027 
01028         // now, vertex program setup.
01029         _LastSetupGLArrayVertexProgram= true;
01030     }
01031 }
01032 
01033 // ***************************************************************************
01034 void        CDriverGL::toggleGlArraysForARBVertexProgram()
01035 {
01036     H_AUTO_OGL(CDriverGL_toggleGlArraysForARBVertexProgram)
01037     // If change of setup type, must disable olds.
01038     //=======================
01039 
01040     // If last was a VertexProgram setup, and now it is a standard GL array setup.
01041     if( _LastSetupGLArrayVertexProgram && !isVertexProgramEnabled () )
01042     {
01043         if (_Extensions.ATITextureEnvCombine3)
01044         {
01045             // fix for ATI : when switching from Vertex Program to fixed Pipe, must clean texture, otherwise texture may be disabled in next render
01046             // (seems to be a driver bug)
01047             ITexture *oldTex[IDRV_MAT_MAXTEXTURES];
01048             for(uint stage=0 ; stage < inlGetNumTextStages() ; stage++)
01049             {
01050                 oldTex[stage] = _CurrentTexture[stage];
01051                 // activate the texture, or disable texturing if NULL.
01052                 activateTexture(stage, NULL);
01053             }
01054             glBegin(GL_QUADS);
01055             glVertex4f(0.f, 0.f, 0.f, 1.f);
01056             glVertex4f(0.f, 0.f, 0.f, 1.f);
01057             glVertex4f(0.f, 0.f, 0.f, 1.f);
01058             glVertex4f(0.f, 0.f, 0.f, 1.f);
01059             glEnd();
01060             for(uint stage=0 ; stage<inlGetNumTextStages() ; stage++)
01061             {
01062                 // activate the texture, or disable texturing if NULL.
01063                 activateTexture(stage, oldTex[stage]);
01064             }
01065         }
01066 
01067         // Disable all VertexAttribs.
01068         for (uint value=0; value<CVertexBuffer::NumValue; value++)
01069         {
01070             // Index
01071             uint glIndex=GLVertexAttribIndex[value];
01072             _DriverGLStates.enableVertexAttribArrayARB(glIndex, false);
01073         }
01074         // no more a vertex program setup.
01075         _LastSetupGLArrayVertexProgram= false;
01076     }
01077 
01078     // If last was a standard GL array setup, and now it is a VertexProgram setup.
01079     if( !_LastSetupGLArrayVertexProgram && isVertexProgramEnabled () )
01080     {
01081         // Disable all standards ptrs.
01082         _DriverGLStates.enableVertexArray(false);
01083         _DriverGLStates.enableNormalArray(false);
01084         _DriverGLStates.enableColorArray(false);
01085         _DriverGLStates.enableSecondaryColorArray(false);
01086         for(uint i=0; i<inlGetNumTextStages(); i++)
01087         {
01088             _DriverGLStates.clientActiveTextureARB(i);
01089             _DriverGLStates.enableTexCoordArray(false);
01090         }
01091         // now, vertex program setup.
01092         _LastSetupGLArrayVertexProgram= true;
01093     }
01094 }
01095 
01096 
01097 
01098 // ***************************************************************************
01099 void        CDriverGL::toggleGlArraysForEXTVertexShader()
01100 {
01101     H_AUTO_OGL(CDriverGL_toggleGlArraysForEXTVertexShader)
01102     // If change of setup type, must disable olds.
01103     //=======================
01104 
01105 
01106     // If last was a VertexProgram setup, and now it is a standard GL array setup.
01107     if( _LastSetupGLArrayVertexProgram && !isVertexProgramEnabled () )
01108     {
01109         CVertexProgram *vp = _LastSetuppedVP;
01110         if (vp)
01111         {
01112             CVertexProgamDrvInfosGL *drvInfo = NLMISC::safe_cast<CVertexProgamDrvInfosGL *>((IVertexProgramDrvInfos *) vp->_DrvInfo);
01113             if (drvInfo)
01114             {
01115                 // Disable all VertexAttribs.
01116                 for (uint value=0; value<CVertexBuffer::NumValue; value++)
01117                 {
01118                     _DriverGLStates.enableVertexAttribArrayForEXTVertexShader(value, false, drvInfo->Variants);
01119                 }
01120             }
01121         }
01122         // no more a vertex program setup.
01123         _LastSetupGLArrayVertexProgram= false;
01124     }
01125 
01126     // If last was a standard GL array setup, and now it is a VertexProgram setup.
01127     if( !_LastSetupGLArrayVertexProgram && isVertexProgramEnabled () )
01128     {
01129         // Disable all standards ptrs.
01130         _DriverGLStates.enableVertexArray(false);
01131         _DriverGLStates.enableNormalArray(false);
01132         _DriverGLStates.enableColorArray(false);
01133         _DriverGLStates.enableSecondaryColorArray(false);
01134         for(uint i=0; i<inlGetNumTextStages(); i++)
01135         {
01136             _DriverGLStates.clientActiveTextureARB(i);
01137             _DriverGLStates.enableTexCoordArray(false);
01138         }
01139 
01140 
01141         // now, vertex program setup.
01142         _LastSetupGLArrayVertexProgram= true;
01143     }
01144 }
01145 
01146 // ***************************************************************************
01147 void        CDriverGL::setupGlArraysForNVVertexProgram(CVertexBufferInfo &vb)
01148 {
01149     H_AUTO_OGL(CDriverGL_setupGlArraysForNVVertexProgram)
01150     uint16  flags= vb.VertexFormat;
01151 
01152     if (vb.VBMode == CVertexBufferInfo::HwARB)
01153         _DriverGLStates.bindARBVertexBuffer(vb.VertexObjectId);
01154 
01155     // For each value
01156     for (uint value=0; value<CVertexBuffer::NumValue; value++)
01157     {
01158         //nldebug("3D:   value = %d", value);
01159         // Flag
01160         uint16 flag=1<<value;
01161 
01162         // Type
01163         CVertexBuffer::TType type=vb.Type[value];
01164 
01165         // Index
01166         uint glIndex=GLVertexAttribIndex[value];
01167 
01168         // Not setuped value and used
01169         if (flags & flag)
01170         {
01171             /* OpenGL Driver Bug with VertexProgram, UChar4 type, and VertexArrayRange.
01172                 Don't work and lead to very poor performance (1/10) (VAR is "disabled").
01173             */
01174             // Test if can use glColorPointer() / glSecondaryColorPointerEXT() instead.
01175             if( (glIndex==3 || glIndex==4) )
01176             {
01177                 if( type == CVertexBuffer::UChar4 )
01178                 {
01179                     // Must disable VertexAttrib array.
01180                     _DriverGLStates.enableVertexAttribArray(glIndex, false);
01181 
01182                     // Active this value, with standard gl calls
01183                     if(glIndex==3)
01184                     {
01185                         // Primary color
01186                         _DriverGLStates.enableColorArray(true);
01187                         glColorPointer(4,GL_UNSIGNED_BYTE, vb.VertexSize, vb.ValuePtr[value]);
01188                     }
01189                     else
01190                     {
01191                         // Secondary color
01192                         _DriverGLStates.enableSecondaryColorArray(true);
01193                         nglSecondaryColorPointerEXT(4,GL_UNSIGNED_BYTE, vb.VertexSize, vb.ValuePtr[value]);
01194                     }
01195                 }
01196                 else
01197                 {
01198                     // Can use normal VertexAttribArray.
01199                     // Disable first standard Color Array.
01200                     if(glIndex==3)
01201                         _DriverGLStates.enableColorArray(false);
01202                     else
01203                         _DriverGLStates.enableSecondaryColorArray(false);
01204 
01205                     // Active this value
01206                     _DriverGLStates.enableVertexAttribArray(glIndex, true);
01207                     nglVertexAttribPointerNV (glIndex, NumCoordinatesType[type], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
01208                 }
01209             }
01210             // Else normal case, can't do anything for other values with UChar4....
01211             else
01212             {
01213                 // Active this value
01214                 _DriverGLStates.enableVertexAttribArray(glIndex, true);
01215                 nglVertexAttribPointerNV (glIndex, NumCoordinatesType[type], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
01216             }
01217         }
01218         else
01219         {
01220             _DriverGLStates.enableVertexAttribArray(glIndex, false);
01221             /* OpenGL Driver Bug with VertexProgram, UChar4 type, and VertexArrayRange.
01222                 Must also disable colorArray in standard gl calls.
01223             */
01224             if(glIndex==3)
01225                 _DriverGLStates.enableColorArray(false);
01226             else if(glIndex==4)
01227                 _DriverGLStates.enableSecondaryColorArray(false);
01228         }
01229     }
01230 
01231     if (vb.VBMode == CVertexBufferInfo::HwARB)
01232         _DriverGLStates.bindARBVertexBuffer(0);
01233 
01234 }
01235 
01236 // tells for each vertex argument if it must be normalized when it is an integral type
01237 static const GLboolean ARBVertexProgramMustNormalizeAttrib[] =
01238 {
01239     GL_FALSE, // Position
01240     GL_TRUE,  // Normal
01241     GL_FALSE, // TexCoord0
01242     GL_FALSE, // TexCoord1
01243     GL_FALSE, // TexCoord2
01244     GL_FALSE, // TexCoord3
01245     GL_FALSE, // TexCoord4
01246     GL_FALSE, // TexCoord5
01247     GL_FALSE, // TexCoord6
01248     GL_FALSE, // TexCoord7
01249     GL_TRUE,  // PrimaryColor
01250     GL_TRUE,  // SecondaryColor
01251     GL_TRUE,  // Weight
01252     GL_FALSE, // PaletteSkin
01253     GL_FALSE, // Fog
01254     GL_FALSE, // Empty
01255 };
01256 
01257 // ***************************************************************************
01258 void        CDriverGL::setupGlArraysForARBVertexProgram(CVertexBufferInfo &vb)
01259 {
01260     H_AUTO_OGL(CDriverGL_setupGlArraysForARBVertexProgram)
01261 
01262     uint32  flags= vb.VertexFormat;
01263 
01264     nlctassert(CVertexBuffer::NumValue == sizeof(ARBVertexProgramMustNormalizeAttrib) / sizeof(ARBVertexProgramMustNormalizeAttrib[0]));
01265 
01266     if (vb.VBMode == CVertexBufferInfo::HwARB)
01267     {
01268         _DriverGLStates.bindARBVertexBuffer(vb.VertexObjectId);
01269     }
01270 
01271     // special case if the buffer is an ATI_vertex_array_object
01272     if (vb.VBMode == CVertexBufferInfo::HwATI)
01273     {
01274         // For each value
01275         for (uint value=0; value<CVertexBuffer::NumValue; value++)
01276         {
01277             // Flag
01278             uint16 flag=1<<value;
01279 
01280             // Type
01281             CVertexBuffer::TType type=vb.Type[value];
01282             {
01283                 // Index
01284                 uint glIndex=GLVertexAttribIndex[value];
01285                 // Not setuped value and used
01286                 if (flags & flag)
01287                 {
01288                     _DriverGLStates.enableVertexAttribArrayARB(glIndex, true);
01289                     GLboolean mustNormalize = GL_FALSE;
01290                     if (GLTypeIsIntegral[type])
01291                     {
01292                         mustNormalize = ARBVertexProgramMustNormalizeAttrib[value];
01293                     }
01294                     nglVertexAttribArrayObjectATI(glIndex, NumCoordinatesType[type], GLType[type], mustNormalize, vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[value]);
01295                 }
01296                 else
01297                 {
01298                     _DriverGLStates.enableVertexAttribArrayARB(glIndex, false);
01299                 }
01300             }
01301         }
01302     }
01303     else
01304     {
01305         // For each value
01306         for (uint value=0; value<CVertexBuffer::NumValue; value++)
01307         {
01308             // Flag
01309             uint16 flag=1<<value;
01310 
01311             // Type
01312             CVertexBuffer::TType type=vb.Type[value];
01313             {
01314                 // Index
01315                 uint glIndex=GLVertexAttribIndex[value];
01316                 // Not setuped value and used
01317                 if (flags & flag)
01318                 {
01319                     _DriverGLStates.enableVertexAttribArrayARB(glIndex, true);
01320                     GLboolean mustNormalize = GL_FALSE;
01321                     if (GLTypeIsIntegral[type])
01322                     {
01323                         mustNormalize = ARBVertexProgramMustNormalizeAttrib[value];
01324                     }
01325                     nglVertexAttribPointerARB(glIndex, NumCoordinatesType[type], GLType[type], mustNormalize, vb.VertexSize, vb.ValuePtr[value]);
01326                 }
01327                 else
01328                 {
01329                     _DriverGLStates.enableVertexAttribArrayARB(glIndex, false);
01330                 }
01331             }
01332         }
01333     }
01334 }
01335 
01336 
01337 
01338 // ***************************************************************************
01339 void        CDriverGL::setupGlArraysForEXTVertexShader(CVertexBufferInfo &vb)
01340 {
01341     H_AUTO_OGL(CDriverGL_setupGlArraysForEXTVertexShader)
01342 
01343 
01344     CVertexProgram *vp = _LastSetuppedVP;
01345     if (!vp) return;
01346     CVertexProgamDrvInfosGL *drvInfo = NLMISC::safe_cast<CVertexProgamDrvInfosGL *>((IVertexProgramDrvInfos *) vp->_DrvInfo);
01347     if (!drvInfo) return;
01348 
01349     uint32  flags= vb.VertexFormat;
01350 
01351 
01352     if (vb.VBMode == CVertexBufferInfo::HwARB)
01353     {
01354         _DriverGLStates.bindARBVertexBuffer(vb.VertexObjectId);
01355     }
01356 
01357     // For each value
01358     for (uint value=0; value<CVertexBuffer::NumValue; value++)
01359     {
01360         // Flag
01361         uint16 flag=1<<value;
01362 
01363         // Type
01364         CVertexBuffer::TType type=vb.Type[value];
01365 
01366         // Index
01367         uint glIndex=GLVertexAttribIndex[value];
01368 
01369         // Not setuped value and used
01370         if (flags & flag & drvInfo->UsedVertexComponents)
01371         {
01372             _DriverGLStates.enableVertexAttribArrayForEXTVertexShader(glIndex, true, drvInfo->Variants);
01373             // use variant or open gl standard array
01374             if (vb.VBMode == CVertexBufferInfo::HwATI)
01375             {
01376                 switch(value)
01377                 {
01378                     case CVertexBuffer::Position: // position
01379                     {
01380                         nlassert(NumCoordinatesType[type] >= 2);
01381                         nglArrayObjectATI(GL_VERTEX_ARRAY, NumCoordinatesType[type], GLType[type], vb.VertexSize, vb.VertexObjectId, (ptrdiff_t)  vb.ValuePtr[CVertexBuffer::Position]);
01382                     }
01383                     break;
01384                     case CVertexBuffer::Weight: // skin weight
01385                     {
01386                         nlassert(NumCoordinatesType[type] == 4); // variant, only 4 component supported
01387                         nglVariantArrayObjectATI(drvInfo->Variants[CDriverGL::EVSSkinWeightVariant], GLType[type], vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[CVertexBuffer::Weight]);
01388                     }
01389                     break;
01390                     case CVertexBuffer::Normal: // normal
01391                     {
01392                         nlassert(NumCoordinatesType[type] == 3); // must have 3 components for normals
01393                         nglArrayObjectATI(GL_NORMAL_ARRAY, 3, GLType[type], vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[value]);
01394                     }
01395                     break;
01396                     case CVertexBuffer::PrimaryColor: // color
01397                     {
01398                         nlassert(NumCoordinatesType[type] >= 3); // must have 3 or 4 components for primary color
01399                         nglArrayObjectATI(GL_COLOR_ARRAY, NumCoordinatesType[type], GLType[type], vb.VertexSize, vb.VertexObjectId, (ptrdiff_t)  vb.ValuePtr[CVertexBuffer::PrimaryColor]);
01400                     }
01401                     break;
01402                     case CVertexBuffer::SecondaryColor: // secondary color
01403                     {
01404                         // implemented using a variant, as not available with EXTVertexShader
01405                         nlassert(NumCoordinatesType[type] == 4); // variant, only 4 component supported
01406                         nglVariantArrayObjectATI(drvInfo->Variants[CDriverGL::EVSSecondaryColorVariant], GLType[type], vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[CVertexBuffer::SecondaryColor]);
01407                     }
01408                     break;
01409                     case CVertexBuffer::Fog: // fog coordinate
01410                     {
01411                         // implemented using a variant
01412                         nlassert(NumCoordinatesType[type] == 4); // variant, only 4 component supported
01413                         nglVariantArrayObjectATI(drvInfo->Variants[CDriverGL::EVSFogCoordsVariant], GLType[type], vb.VertexSize, vb.VertexObjectId, (ptrdiff_t)  vb.ValuePtr[CVertexBuffer::Fog]);
01414                     }
01415                     break;
01416                     case CVertexBuffer::PaletteSkin: // palette skin
01417                     {
01418                         // implemented using a variant
01419                         nlassert(NumCoordinatesType[type] == 4); // variant, only 4 component supported
01420                         nglVariantArrayObjectATI(drvInfo->Variants[CDriverGL::EVSPaletteSkinVariant], GLType[type], vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[CVertexBuffer::PaletteSkin]);
01421                     }
01422                     break;
01423                     case CVertexBuffer::Empty: // empty
01424                         nlstop
01425                         break;
01426                     case CVertexBuffer::TexCoord0:
01427                     case CVertexBuffer::TexCoord1:
01428                     case CVertexBuffer::TexCoord2:
01429                     case CVertexBuffer::TexCoord3:
01430                     case CVertexBuffer::TexCoord4:
01431                     case CVertexBuffer::TexCoord5:
01432                     case CVertexBuffer::TexCoord6:
01433                     case CVertexBuffer::TexCoord7:
01434                     {
01435                         _DriverGLStates.clientActiveTextureARB(value - CVertexBuffer::TexCoord0);
01436                         nglArrayObjectATI(GL_TEXTURE_COORD_ARRAY, NumCoordinatesType[type], GLType[type], vb.VertexSize, vb.VertexObjectId, (ptrdiff_t)  vb.ValuePtr[value]);
01437                     }
01438                     break;
01439                     default:
01440                         nlstop; // invalid value
01441                     break;
01442                 }
01443             }
01444             else
01445             {
01446                 switch(value)
01447                 {
01448                         case CVertexBuffer::Position: // position
01449                         {
01450                             nlassert(NumCoordinatesType[type] >= 2);
01451                             glVertexPointer(NumCoordinatesType[type], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
01452                         }
01453                         break;
01454                         case CVertexBuffer::Weight: // skin weight
01455                         {
01456                             nlassert(NumCoordinatesType[type] == 4); // variant, only 4 component supported
01457                             nglVariantPointerEXT(drvInfo->Variants[CDriverGL::EVSSkinWeightVariant], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
01458                         }
01459                         break;
01460                         case CVertexBuffer::Normal: // normal
01461                         {
01462                             nlassert(NumCoordinatesType[type] == 3); // must have 3 components for normals
01463                             glNormalPointer(GLType[type], vb.VertexSize, vb.ValuePtr[CVertexBuffer::Normal]);
01464                         }
01465                         break;
01466                         case CVertexBuffer::PrimaryColor: // color
01467                         {
01468                             nlassert(NumCoordinatesType[type] >= 3); // must have 3 or 4 components for primary color
01469                             glColorPointer(NumCoordinatesType[type], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
01470                         }
01471                         break;
01472                         case CVertexBuffer::SecondaryColor: // secondary color
01473                         {
01474                             // implemented using a variant, as not available with EXTVertexShader
01475                             nlassert(NumCoordinatesType[type] == 4); // variant, only 4 component supported
01476                             nglVariantPointerEXT(drvInfo->Variants[CDriverGL::EVSSecondaryColorVariant], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
01477                         }
01478                         break;
01479                         case CVertexBuffer::Fog: // fog coordinate
01480                         {
01481                             // implemented using a variant
01482                             nlassert(NumCoordinatesType[type] == 4); // variant, only 4 component supported
01483                             nglVariantPointerEXT(drvInfo->Variants[CDriverGL::EVSFogCoordsVariant], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
01484                         }
01485                         break;
01486                         case CVertexBuffer::PaletteSkin: // palette skin
01487                         {
01488                             // implemented using a variant
01489                             nlassert(NumCoordinatesType[type] == 4); // variant, only 4 component supported
01490                             nglVariantPointerEXT(drvInfo->Variants[CDriverGL::EVSPaletteSkinVariant], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
01491                         }
01492                         break;
01493                         case CVertexBuffer::Empty: // empty
01494                             nlstop
01495                         break;
01496                         case CVertexBuffer::TexCoord0:
01497                         case CVertexBuffer::TexCoord1:
01498                         case CVertexBuffer::TexCoord2:
01499                         case CVertexBuffer::TexCoord3:
01500                         case CVertexBuffer::TexCoord4:
01501                         case CVertexBuffer::TexCoord5:
01502                         case CVertexBuffer::TexCoord6:
01503                         case CVertexBuffer::TexCoord7:
01504                         {
01505                             _DriverGLStates.clientActiveTextureARB(value - CVertexBuffer::TexCoord0);
01506                             nglArrayObjectATI(GL_TEXTURE_COORD_ARRAY, NumCoordinatesType[type], GLType[type], vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[value]);
01507                         }
01508                         break;
01509                         default:
01510                             nlstop; // invalid value
01511                         break;
01512                 }
01513             }
01514         }
01515         else
01516         {
01517             _DriverGLStates.enableVertexAttribArrayForEXTVertexShader(glIndex, false, drvInfo->Variants);
01518         }
01519     }
01520 }
01521 
01522 
01523 
01524 // ***************************************************************************
01525 void        CDriverGL::setupGlArrays(CVertexBufferInfo &vb)
01526 {
01527     H_AUTO_OGL(CDriverGL_setupGlArrays)
01528 
01529     // Standard case (NVVertexProgram or no vertex program case)
01530     if (_Extensions.NVVertexProgram)
01531     {
01532         toggleGlArraysForNVVertexProgram();
01533         // Use a vertex program ?
01534         if (!isVertexProgramEnabled ())
01535         {
01536             setupGlArraysStd(vb);
01537         }
01538         else
01539         {
01540             setupGlArraysForNVVertexProgram(vb);
01541         }
01542     }
01543     else if (_Extensions.ARBVertexProgram)
01544     {
01545         toggleGlArraysForARBVertexProgram();
01546         // Use a vertex program ?
01547         if (!isVertexProgramEnabled ())
01548         {
01549             setupGlArraysStd(vb);
01550         }
01551         else
01552         {
01553             setupGlArraysForARBVertexProgram(vb);
01554         }
01555     }
01556     else if (_Extensions.EXTVertexShader)
01557     {
01558         toggleGlArraysForEXTVertexShader();
01559         // Use a vertex program ?
01560         if (!isVertexProgramEnabled ())
01561         {
01562             setupGlArraysStd(vb);
01563         }
01564         else
01565         {
01566             setupGlArraysForEXTVertexShader(vb);
01567         }
01568     }
01569     else
01570     {
01571         // no vertex programs
01572         setupGlArraysStd(vb);
01573     }
01574 }
01575 
01576 
01577 // ***************************************************************************
01578 void        CVertexBufferInfo::setupVertexBuffer(CVertexBuffer &vb)
01579 {
01580     H_AUTO_OGL(CDriverGL_setupVertexBuffer)
01581     sint    i;
01582     VertexFormat= vb.getVertexFormat();
01583     VertexSize= vb.getVertexSize();
01584     NumVertices= vb.getNumVertices();
01585 
01586     // Lock the buffer
01587     CVertexBufferReadWrite access;
01588     uint8 *ptr;
01589     CVBDrvInfosGL *info= safe_cast<CVBDrvInfosGL*>((IVBDrvInfos*)vb.DrvInfos);
01590     nlassert (info);
01591     if (info->_VBHard)
01592     {
01593         ptr = (uint8*)info->_VBHard->getPointer();
01594         info->_VBHard->setupVBInfos(*this);
01595     }
01596     else
01597     {
01598         nlassert (info->_SystemMemory);
01599         ptr = info->_SystemMemory;
01600         VBMode = SysMem;
01601     }
01602 
01603     // Get value pointer
01604     for (i=0; i<CVertexBuffer::NumValue; i++)
01605     {
01606         // Value used ?
01607         if (VertexFormat&(1<<i))
01608         {
01609             // Get the pointer
01610             ValuePtr[i]= ptr+vb.getValueOffEx((CVertexBuffer::TValue)i);
01611 
01612             // Type of the value
01613             Type[i]=vb.getValueType (i);
01614         }
01615     }
01616 
01617     // Copy the UVRouting table
01618     const uint8 *uvRouting = vb.getUVRouting();
01619     for (i=0; i<CVertexBuffer::MaxStage; i++)
01620     {
01621         UVRouting[i] = uvRouting[i];
01622     }
01623 }
01624 
01625 
01626 // ***************************************************************************
01627 void            CDriverGL::resetVertexArrayRange()
01628 {
01629     H_AUTO_OGL(CDriverGL_resetVertexArrayRange)
01630     if(_CurrentVertexBufferHard)
01631     {
01632         // Must ensure it has ended any drawing
01633         _CurrentVertexBufferHard->lock();
01634         _CurrentVertexBufferHard->unlock();
01635         // disable it
01636         _CurrentVertexBufferHard->disable();
01637     }
01638     // Clear any VertexBufferHard created.
01639     _VertexBufferHardSet.clear();
01640 
01641     // After, Clear the 2 vertexArrayRange, if any.
01642     if(_AGPVertexArrayRange)
01643         _AGPVertexArrayRange->free();
01644     if(_VRAMVertexArrayRange)
01645         _VRAMVertexArrayRange->free();
01646 }
01647 
01648 
01649 // ***************************************************************************
01650 bool            CDriverGL::initVertexBufferHard(uint agpMem, uint vramMem)
01651 {
01652     H_AUTO_OGL(CDriverGL_initVertexBufferHard)
01653     if(!supportVertexBufferHard())
01654         return false;
01655 
01656     // must be supported
01657     if(!_AGPVertexArrayRange || !_VRAMVertexArrayRange)
01658         return false;
01659 
01660     // First, reset any VBHard created.
01661     resetVertexArrayRange();
01662     bool    ok= true;
01663 
01664     // Try to allocate AGPMemory.
01665     if(agpMem>0)
01666     {
01667         agpMem&= ~15;   // ensure 16-bytes aligned mem count (maybe useful :) ).
01668         agpMem= max(agpMem, (uint)NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE);
01669         while(agpMem>= NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE)
01670         {
01671             if(_AGPVertexArrayRange->allocate(agpMem, CVertexBuffer::AGPPreferred))
01672             {
01673                 nlinfo("3D: %.u vertices supported", _MaxVerticesByVBHard);
01674                 nlinfo("3D: Success to allocate %.1f Mo of AGP VAR Ram", agpMem / 1000000.f);
01675                 break;
01676             }
01677             else
01678             {
01679                 agpMem/=2;
01680                 agpMem &=~15;
01681             }
01682         }
01683 
01684         if(agpMem< NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE)
01685         {
01686             nlinfo("3D: %.u vertices supported", _MaxVerticesByVBHard);
01687             nlinfo("3D: Failed to allocate %.1f Mo of AGP VAR Ram", NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE / 1000000.f);
01688             ok= false;
01689         }
01690     }
01691 
01692 
01693     // Try to allocate VRAMMemory.
01694     if(vramMem>0)
01695     {
01696         vramMem&= ~15;  // ensure 16-bytes aligned mem count (maybe useful :) ).
01697         vramMem= max(vramMem, (uint)NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE);
01698         while(vramMem>= NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE)
01699         {
01700             if(_VRAMVertexArrayRange->allocate(vramMem, CVertexBuffer::StaticPreferred))
01701                 break;
01702             else
01703             {
01704                 vramMem/=2;
01705                 vramMem &=~15;
01706             }
01707         }
01708 
01709         if(vramMem< NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE)
01710         {
01711             ok= false;
01712         }
01713     }
01714 
01715 
01716     return ok;
01717 }
01718 
01719 
01720 // ***************************************************************************
01721 uint32              CDriverGL::getAvailableVertexAGPMemory ()
01722 {
01723     H_AUTO_OGL(CDriverGL_getAvailableVertexAGPMemory )
01724     if (_AGPVertexArrayRange)
01725         return _AGPVertexArrayRange->sizeAllocated();
01726     else
01727         return 0;
01728 }
01729 
01730 
01731 // ***************************************************************************
01732 uint32              CDriverGL::getAvailableVertexVRAMMemory ()
01733 {
01734     H_AUTO_OGL(CDriverGL_getAvailableVertexVRAMMemory )
01735     if (_VRAMVertexArrayRange)
01736         return _VRAMVertexArrayRange->sizeAllocated();
01737     else
01738         return 0;
01739 }
01740 
01741 
01742 // ***************************************************************************
01743 void                CDriverGL::fenceOnCurVBHardIfNeeded(IVertexBufferHardGL *newVBHard)
01744 {
01745     H_AUTO_OGL(CDriverGL_fenceOnCurVBHardIfNeeded)
01746     // If old is not a VBHard, or if not a NVidia VBHard, no-op.
01747     if( _CurrentVertexBufferHard==NULL || !_CurrentVertexBufferHard->VBType == IVertexBufferHardGL::NVidiaVB)
01748         return;
01749 
01750     // if we do not activate the same (NB: newVBHard==NULL if not a VBHard).
01751     if(_CurrentVertexBufferHard!=newVBHard)
01752     {
01753         // get NVidia interface
01754         CVertexBufferHardGLNVidia   *vbHardNV= static_cast<CVertexBufferHardGLNVidia*>(_CurrentVertexBufferHard);
01755 
01756         // If some render() have been done with this VB.
01757         if( vbHardNV->GPURenderingAfterFence )
01758         {
01759             /*
01760                 Since we won't work with this VB for a long time, we set a fence.
01761 
01762                 NB: if the fence was previously set. NV_Fence Specification says that the new ONE replaces it.
01763                 This is EXACTLY what we wants, since the old one is no more interesting.
01764 
01765                 NB: never insert a fence for said "Static Lock" VBHard. Those VBHard are said to be "static"
01766                 therefore, user should never modify them (else lock() is much slower...)
01767             */
01768             if( !vbHardNV->getLockHintStatic() )
01769                 vbHardNV->setFence();
01770             // Since we have set a new Fence, we won't need to do it at next vbHardNV->lock()
01771             vbHardNV->GPURenderingAfterFence= false;
01772         }
01773     }
01774 }
01775 
01776 // ***************************************************************************
01777 
01778 CIndexBufferInfo::CIndexBufferInfo()
01779 {
01780     H_AUTO_OGL(CIndexBufferInfo_CIndexBufferInfo)
01781     _Values = NULL;
01782 }
01783 
01784 // ***************************************************************************
01785 
01786 void CIndexBufferInfo::setupIndexBuffer(CIndexBuffer &ib)
01787 {
01788     H_AUTO_OGL(CIndexBufferInfo_setupIndexBuffer)
01789     CIndexBufferReadWrite access;
01790     ib.lock (access);
01791     _Values = access.getPtr();
01792     _Format = access.getFormat();
01793 }
01794 
01795 // ***************************************************************************
01796 
01797 } // NL3D

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