Show bonus/malus timer text if available
[ryzomcore.git] / nel / src / 3d / driver / opengl / driver_opengl_vertex.cpp
blob80c84ef98f395ca8f487206c744ff56acc8c48d6
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013-2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "stdopengl.h"
22 #include "driver_opengl.h"
23 #include "nel/3d/index_buffer.h"
24 #include "driver_opengl_vertex_buffer_hard.h"
29 using namespace std;
30 using namespace NLMISC;
32 #ifdef DEBUG_NEW
33 #define new DEBUG_NEW
34 #endif
38 // ***************************************************************************
39 // Flags for software vertex skinning.
40 #define NL3D_DRV_SOFTSKIN_VNEEDCOMPUTE 3
41 #define NL3D_DRV_SOFTSKIN_VMUSTCOMPUTE 1
42 #define NL3D_DRV_SOFTSKIN_VCOMPUTED 0
43 // 3 means "vertex may need compute".
44 // 1 means "Primitive say vertex must be computed".
45 // 0 means "vertex is computed".
48 // 500K min.
49 #define NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE (512*1024)
55 namespace NL3D {
57 #ifdef NL_STATIC
58 #ifdef USE_OPENGLES
59 namespace NLDRIVERGLES {
60 #else
61 namespace NLDRIVERGL {
62 #endif
63 #endif
65 // ***************************************************************************
67 CVBDrvInfosGL::CVBDrvInfosGL(CDriverGL *drv, ItVBDrvInfoPtrList it, CVertexBuffer *vb) : IVBDrvInfos(drv, it, vb)
69 H_AUTO_OGL(CVBDrvInfosGL_CVBDrvInfosGL)
70 _DriverGL = drv;
71 _VBHard = NULL;
72 _SystemMemory = NULL;
75 // ***************************************************************************
77 CVBDrvInfosGL::~CVBDrvInfosGL()
79 H_AUTO_OGL(CVBDrvInfosGL_CVBDrvInfosGLDtor)
80 // Restore non resident memory
81 if (VertexBufferPtr)
83 VertexBufferPtr->setLocation(CVertexBuffer::NotResident);
84 VertexBufferPtr = NULL;
87 if (_VBHard)
89 _VBHard->disable();
90 _DriverGL->_VertexBufferHardSet.erase(_VBHard);
92 if (_SystemMemory)
94 delete [] _SystemMemory;
96 _SystemMemory = NULL;
97 _VBHard = NULL;
100 // ***************************************************************************
101 uint8 *CVBDrvInfosGL::lock (uint /* first */, uint /* last */, bool /* readOnly */)
103 H_AUTO_OGL(CVBDrvInfosGL_lock)
104 if (_VBHard)
106 return (uint8*)_VBHard->lock ();
108 else
110 // Should be a system memory
111 nlassert (_SystemMemory);
112 return _SystemMemory;
116 // ***************************************************************************
117 void CVBDrvInfosGL::unlock (uint first, uint last)
119 H_AUTO_OGL(CVBDrvInfosGL_unlock)
120 if (_VBHard)
122 _VBHard->unlock(first, last);
124 else
126 // Should be a system memory
127 nlassert (_SystemMemory);
131 // ***************************************************************************
132 bool CDriverGL::setupVertexBuffer(CVertexBuffer& VB)
134 H_AUTO_OGL(CDriverGL_setupVertexBuffer)
135 // 2. If necessary, do modifications.
136 //==================================
137 const bool touched = (VB.getTouchFlags() & (CVertexBuffer::TouchedReserve|CVertexBuffer::TouchedVertexFormat)) != 0;
138 if( touched || (VB.DrvInfos == NULL))
140 // delete first
141 if(VB.DrvInfos)
142 delete VB.DrvInfos;
143 VB.DrvInfos = NULL;
145 // create only if some vertices
146 if(VB.getNumVertices())
148 // 1. Retrieve/Create driver shader.
149 //==================================
150 // insert into driver list. (so it is deleted when driver is deleted).
151 ItVBDrvInfoPtrList it= _VBDrvInfos.insert(_VBDrvInfos.end(), (NL3D::IVBDrvInfos*)NULL);
152 // create and set iterator, for future deletion.
153 CVBDrvInfosGL *info = new CVBDrvInfosGL(this, it, &VB);
154 *it= VB.DrvInfos = info;
156 // Preferred memory, AGPVolatile only goes through when ARBMapBufferRange is available
157 CVertexBuffer::TPreferredMemory preferred = VB.getPreferredMemory ();
158 if ((preferred == CVertexBuffer::RAMVolatile) || (preferred == CVertexBuffer::AGPVolatile && !_Extensions.ARBMapBufferRange))
159 preferred = CVertexBuffer::RAMPreferred;
160 const uint size = VB.capacity()*VB.getVertexSize();
161 uint preferredMemory = _Extensions.DisableHardwareVertexArrayAGP ? CVertexBuffer::RAMPreferred : preferred;
162 while (preferredMemory != CVertexBuffer::RAMPreferred)
164 // Vertex buffer hard
165 info->_VBHard = createVertexBufferHard(size, VB.capacity(), (CVertexBuffer::TPreferredMemory)preferredMemory, &VB);
166 if (info->_VBHard)
167 break;
169 if ((CVertexBuffer::TPreferredMemory)preferredMemory == CVertexBuffer::AGPVolatile)
171 preferredMemory = CVertexBuffer::RAMPreferred;
172 break;
174 preferredMemory--;
177 // No memory found ? Use system memory
178 if (info->_VBHard == NULL)
180 nlassert (info->_SystemMemory == NULL);
181 info->_SystemMemory = new uint8[size];
184 // Upload the data
185 VB.setLocation(preferredMemory == CVertexBuffer::AGPVolatile ? CVertexBuffer::AGPResident : (CVertexBuffer::TLocation)preferredMemory);
189 return true;
193 // ***************************************************************************
194 bool CDriverGL::activeVertexBuffer(CVertexBuffer& VB)
196 H_AUTO_OGL(CDriverGL_activeVertexBuffer)
197 // NB: must duplicate changes in activeVertexBufferHard()
198 uint32 flags;
200 // In any case, we'll erase any special vertex setup for Lightmap Material
201 _LastVertexSetupIsLightMap= false;
203 // setup
204 if (!setupVertexBuffer(VB))
205 return false;
207 if (VB.getNumVertices()==0)
208 return true;
210 // Fill the buffer if in local memory
211 VB.fillBuffer ();
213 // Get VB flags, to setup matrixes and arrays.
214 flags=VB.getVertexFormat();
217 // 2. Setup Arrays.
218 //===================
219 // For MultiPass Material.
220 CVertexBufferInfo::TVBMode lastVBMode = _LastVB.VBMode;
221 CVBDrvInfosGL *info= safe_cast<CVBDrvInfosGL*>((IVBDrvInfos*)VB.DrvInfos);
222 if (!info->_VBHard || (info->_VBHard && !info->_VBHard->isInvalid()))
224 _LastVB.setupVertexBuffer(VB);
225 if (lastVBMode == CVertexBufferInfo::HwARB && _LastVB.VBMode != CVertexBufferInfo::HwARB)
227 _DriverGLStates.bindARBVertexBuffer(0); // unbind ARB vertex buffer
230 if (info->_VBHard == NULL)
232 // Fence mgt.
233 fenceOnCurVBHardIfNeeded(NULL);
235 // Disable the current vertexBufferHard if setuped.
236 if(_CurrentVertexBufferHard)
237 _CurrentVertexBufferHard->disable();
239 else
241 // 2. Setup Arrays.
242 //===================
244 // Fence mgt.
245 fenceOnCurVBHardIfNeeded(info->_VBHard);
247 // Enable the vertexArrayRange of this array.
248 info->_VBHard->enable();
250 if (!info->_VBHard || (info->_VBHard && !info->_VBHard->isInvalid()))
252 setupGlArrays(_LastVB);
254 return true;
257 // ***************************************************************************
258 bool CDriverGL::activeIndexBuffer(CIndexBuffer& IB)
260 H_AUTO_OGL(CDriverGL_activeIndexBuffer)
261 _LastIB.setupIndexBuffer(IB);
262 return true;
265 // ***************************************************************************
267 bool CDriverGL::renderLines(CMaterial& mat, uint32 firstIndex, uint32 nlines)
269 H_AUTO_OGL(CDriverGL_renderLines)
270 // update matrix and Light in OpenGL if needed
271 refreshRenderSetup();
273 // setup material
274 if ( !setupMaterial(mat) || _LastIB._Values == NULL )
275 return false;
277 if (_CurrentVertexBufferHard && _CurrentVertexBufferHard->isInvalid()) return true;
278 // render primitives.
279 //==============================
280 // start multipass.
281 uint nPass;
282 nPass= beginMultiPass();
283 // draw all passes.
284 for(uint pass=0;pass<nPass; pass++)
286 // setup the pass.
287 setupPass(pass);
288 // draw the primitives.
289 if(nlines)
291 if (_LastIB._Format == CIndexBuffer::Indices16)
293 glDrawElements(GL_LINES,2*nlines,GL_UNSIGNED_SHORT,((uint16 *) _LastIB._Values)+firstIndex);
295 else
297 #ifdef USE_OPENGLES
298 nlerror("not available in OpenGL ES 1.0, only use 16 bits indices");
299 #else
300 nlassert(_LastIB._Format == CIndexBuffer::Indices32);
301 glDrawElements(GL_LINES,2*nlines,GL_UNSIGNED_INT,((uint32 *) _LastIB._Values)+firstIndex);
302 #endif
306 // end multipass.
307 endMultiPass();
309 // Profiling.
310 _PrimitiveProfileIn.NLines+= nlines;
311 _PrimitiveProfileOut.NLines+= nlines;
313 // We have render some prims. inform the VBHard.
314 if(_CurrentVertexBufferHard)
315 _CurrentVertexBufferHard->GPURenderingAfterFence= true;
317 return true;
320 // ***************************************************************************
322 bool CDriverGL::renderTriangles(CMaterial& mat, uint32 firstIndex, uint32 ntris)
324 H_AUTO_OGL(CDriverGL_renderTriangles);
326 // update matrix and Light in OpenGL if needed
327 refreshRenderSetup();
329 // setup material
330 if ( !setupMaterial(mat) || _LastIB._Values == NULL )
331 return false;
333 if (_CurrentVertexBufferHard && _CurrentVertexBufferHard->isInvalid()) return true;
335 // render primitives.
336 //==============================
337 // start multipass.
338 uint nPass;
340 nPass= beginMultiPass();
342 // draw all passes.
343 for(uint pass=0;pass<nPass; pass++)
345 // setup the pass.
346 setupPass(pass);
348 // draw the primitives.
349 if(ntris)
351 if (_LastIB._Format == CIndexBuffer::Indices16)
353 glDrawElements(GL_TRIANGLES,3*ntris,GL_UNSIGNED_SHORT, ((uint16 *) _LastIB._Values)+firstIndex);
355 else
357 #ifdef USE_OPENGLES
358 nlerror("not available in OpenGL ES 1.0, only use 16 bits indices");
359 #else
360 nlassert(_LastIB._Format == CIndexBuffer::Indices32);
361 glDrawElements(GL_TRIANGLES,3*ntris,GL_UNSIGNED_INT, ((uint32 *) _LastIB._Values)+firstIndex);
362 #endif
366 // end multipass.
367 endMultiPass();
370 // Profiling.
371 _PrimitiveProfileIn.NTriangles+= ntris;
372 _PrimitiveProfileOut.NTriangles+= ntris * nPass;
374 // We have render some prims. inform the VBHard.
375 if(_CurrentVertexBufferHard)
376 _CurrentVertexBufferHard->GPURenderingAfterFence= true;
377 return true;
380 // ***************************************************************************
382 bool CDriverGL::renderSimpleTriangles(uint32 firstTri, uint32 ntris)
384 H_AUTO_OGL(CDriverGL_renderSimpleTriangles);
386 nlassert(ntris>0);
388 // update matrix and Light in OpenGL if needed
389 refreshRenderSetup();
391 if (_CurrentVertexBufferHard && _CurrentVertexBufferHard->isInvalid()) return true;
392 // Don't setup any material here.
394 // render primitives.
395 //==============================
396 // NO MULTIPASS HERE!!
397 // draw the primitives. (nb: ntris>0).
399 if (_LastIB._Format == CIndexBuffer::Indices16)
401 glDrawElements(GL_TRIANGLES,3*ntris,GL_UNSIGNED_SHORT, ((uint16 *) _LastIB._Values)+firstTri);
403 else
405 #ifdef USE_OPENGLES
406 nlerror("not available in OpenGL ES 1.0, only use 16 bits indices");
407 #else
408 nlassert(_LastIB._Format == CIndexBuffer::Indices32);
409 glDrawElements(GL_TRIANGLES,3*ntris,GL_UNSIGNED_INT, ((uint32 *) _LastIB._Values)+firstTri);
410 #endif
413 // Profiling.
414 _PrimitiveProfileIn.NTriangles+= ntris;
415 _PrimitiveProfileOut.NTriangles+= ntris;
417 // We have render some prims. inform the VBHard.
418 if(_CurrentVertexBufferHard)
419 _CurrentVertexBufferHard->GPURenderingAfterFence= true;
421 return true;
424 // ***************************************************************************
426 bool CDriverGL::renderRawPoints(CMaterial& mat, uint32 startIndex, uint32 numPoints)
428 H_AUTO_OGL(CDriverGL_renderRawPoints)
429 // update matrix and Light in OpenGL if needed
430 refreshRenderSetup();
432 // setup material
433 if ( !setupMaterial(mat) )
434 return false;
436 if (_CurrentVertexBufferHard && _CurrentVertexBufferHard->isInvalid()) return true;
437 // render primitives.
438 //==============================
439 // start multipass.
440 uint nPass;
441 nPass= beginMultiPass();
442 // draw all passes.
443 for(uint pass=0;pass<nPass; pass++)
445 // setup the pass.
446 setupPass(pass);
447 // draw the primitives.
448 if(numPoints)
449 glDrawArrays(GL_POINTS, startIndex, numPoints);
451 // end multipass.
452 endMultiPass();
455 // Profiling.
456 _PrimitiveProfileIn.NPoints+= numPoints;
457 _PrimitiveProfileOut.NPoints+= numPoints * nPass;
459 // We have render some prims. inform the VBHard.
460 if(_CurrentVertexBufferHard)
461 _CurrentVertexBufferHard->GPURenderingAfterFence= true;
462 return true;
465 // ***************************************************************************
467 bool CDriverGL::renderRawLines(CMaterial& mat, uint32 startIndex, uint32 numLines)
469 H_AUTO_OGL(CDriverGL_renderRawLines)
470 // update matrix and Light in OpenGL if needed
471 refreshRenderSetup();
473 // setup material
474 if ( !setupMaterial(mat) )
475 return false;
477 if (_CurrentVertexBufferHard && _CurrentVertexBufferHard->isInvalid()) return true;
478 // render primitives.
479 //==============================
480 // start multipass.
481 uint nPass;
482 nPass= beginMultiPass();
483 // draw all passes.
484 for(uint pass=0;pass<nPass; pass++)
486 // setup the pass.
487 setupPass(pass);
488 // draw the primitives.
489 if(numLines)
490 glDrawArrays(GL_LINES, startIndex << 1, numLines << 1);
492 // end multipass.
493 endMultiPass();
496 // Profiling.
497 _PrimitiveProfileIn.NLines += numLines ;
498 _PrimitiveProfileOut.NLines += numLines * nPass;
500 // We have render some prims. inform the VBHard.
501 if(_CurrentVertexBufferHard)
502 _CurrentVertexBufferHard->GPURenderingAfterFence= true;
503 return true;
506 // ***************************************************************************
508 bool CDriverGL::renderRawTriangles(CMaterial& mat, uint32 startIndex, uint32 numTris)
510 H_AUTO_OGL(CDriverGL_renderRawTriangles)
511 // update matrix and Light in OpenGL if needed
512 refreshRenderSetup();
514 // setup material
515 if ( !setupMaterial(mat) )
516 return false;
518 if (_CurrentVertexBufferHard && _CurrentVertexBufferHard->isInvalid()) return true;
519 // render primitives.
520 //==============================
521 // start multipass.
522 uint nPass;
523 nPass= beginMultiPass();
524 // draw all passes.
525 for(uint pass=0;pass<nPass; pass++)
527 // setup the pass.
528 setupPass(pass);
529 // draw the primitives.
530 if(numTris)
532 glDrawArrays(GL_TRIANGLES, startIndex*3, numTris*3);
535 // end multipass.
536 endMultiPass();
539 // Profiling.
540 _PrimitiveProfileIn.NTriangles += numTris ;
541 _PrimitiveProfileOut.NTriangles += numTris * nPass;
543 // We have render some prims. inform the VBHard.
544 if(_CurrentVertexBufferHard)
545 _CurrentVertexBufferHard->GPURenderingAfterFence= true;
546 return true;
549 // ***************************************************************************
551 bool CDriverGL::renderRawQuads(CMaterial& mat, uint32 startIndex, uint32 numQuads)
553 H_AUTO_OGL(CDriverGL_renderRawQuads)
554 if (!numQuads) return true;
555 // update matrix and Light in OpenGL if needed
556 refreshRenderSetup();
558 // setup material
559 if ( !setupMaterial(mat) )
560 return false;
562 if (_CurrentVertexBufferHard && _CurrentVertexBufferHard->isInvalid()) return true;
564 const uint32 QUAD_BATCH_SIZE = 2048;
565 static GLshort defaultIndices[QUAD_BATCH_SIZE * 6];
566 static bool init = false;
567 if (!init)
569 // setup the base index buffer
570 for(uint k = 0; k < QUAD_BATCH_SIZE; ++k)
572 // first tri
573 defaultIndices[k * 6] = (GLshort) (k * 4);
574 defaultIndices[k * 6 + 1] = (GLshort) (k * 4 + 1);
575 defaultIndices[k * 6 + 2] = (GLshort) (k * 4 + 2);
576 // second tri
577 defaultIndices[k * 6 + 3] = (GLshort) (k * 4);
578 defaultIndices[k * 6 + 4] = (GLshort) (k * 4 + 2);
579 defaultIndices[k * 6 + 5] = (GLshort) (k * 4 + 3);
582 init = true;
585 // render primitives.
586 //==============================
587 // start multipass.
588 uint nPass;
589 nPass= beginMultiPass();
590 // draw all passes.
591 for(uint pass=0;pass<nPass; pass++)
593 // setup the pass.
594 setupPass(pass);
596 uint32 currIndex = startIndex;
597 uint32 numLeftQuads = numQuads;
599 // draw first batch of quads using the static setupped array
600 if (startIndex < QUAD_BATCH_SIZE)
602 // draw first quads (as pair of tri to have guaranteed orientation)
603 uint numQuadsToDraw = std::min(QUAD_BATCH_SIZE - startIndex, numQuads);
604 glDrawElements(GL_TRIANGLES, 6 * numQuadsToDraw, GL_UNSIGNED_SHORT, defaultIndices + 6 * startIndex);
605 numLeftQuads -= numQuadsToDraw;
606 currIndex += 4 * numQuadsToDraw;
609 // draw remaining quads
610 while (numLeftQuads)
612 // TODO : resetting vertex pointer would avoid the need to rebuild indices each times
613 uint32 numQuadsToDraw = std::min(numLeftQuads, QUAD_BATCH_SIZE);
614 // draw all quads
615 if (4 * numQuadsToDraw + currIndex <= (1 << 16))
617 // indices fits on 16 bits
618 GLshort indices[QUAD_BATCH_SIZE * 6];
619 GLshort *curr = indices;
620 GLshort *end = indices + 6 * numQuadsToDraw;
621 uint16 vertexIndex = (uint16) currIndex;
624 *curr++ = vertexIndex;
625 *curr++ = vertexIndex + 1;
626 *curr++ = vertexIndex + 2;
627 *curr++ = vertexIndex;
628 *curr++ = vertexIndex + 2;
629 *curr++ = vertexIndex + 3;
630 vertexIndex += 4;
632 while(curr != end);
633 glDrawElements(GL_TRIANGLES, 6 * numQuadsToDraw, GL_UNSIGNED_SHORT, indices);
635 else
637 #ifdef USE_OPENGLES
638 nlerror("not available in OpenGL ES 1.0, only use 16 bits indices");
639 #else
640 // indices fits on 32 bits
641 GLint indices[QUAD_BATCH_SIZE * 6];
642 GLint *curr = indices;
643 GLint *end = indices + 6 * numQuadsToDraw;
644 uint32 vertexIndex = currIndex;
647 *curr++ = vertexIndex;
648 *curr++ = vertexIndex + 1;
649 *curr++ = vertexIndex + 2;
650 *curr++ = vertexIndex;
651 *curr++ = vertexIndex + 2;
652 *curr++ = vertexIndex + 3;
653 vertexIndex += 4;
655 while(curr != end);
656 glDrawElements(GL_TRIANGLES, 6 * numQuadsToDraw, GL_UNSIGNED_INT, indices);
657 #endif
659 numLeftQuads -= numQuadsToDraw;
660 currIndex += 4 * numQuadsToDraw;
663 // end multipass.
664 endMultiPass();
667 // Profiling.
668 _PrimitiveProfileIn.NQuads += numQuads ;
669 _PrimitiveProfileOut.NQuads += numQuads * nPass;
671 // We have render some prims. inform the VBHard.
672 if(_CurrentVertexBufferHard)
673 _CurrentVertexBufferHard->GPURenderingAfterFence= true;
674 return true;
677 // ***************************************************************************
679 void CDriverGL::setupUVPtr(uint stage, CVertexBufferInfo &VB, uint uvId)
681 H_AUTO_OGL(CDriverGL_setupUVPtr)
682 // sould not be called with vertex program Array setuped.
683 nlassert(!_LastSetupGLArrayVertexProgram);
685 _DriverGLStates.clientActiveTextureARB(stage);
686 if (VB.VertexFormat & (CVertexBuffer::TexCoord0Flag<<uvId))
688 // Check type, if not supported, just ignore
689 CVertexBuffer::TType uvType = VB.Type[CVertexBuffer::TexCoord0+uvId];
690 if (uvType == CVertexBuffer::Float2 ||
691 uvType == CVertexBuffer::Float3)
693 _DriverGLStates.enableTexCoordArray(true);
694 uint numTexCoord = (uvType == CVertexBuffer::Float2) ? 2 : 3;
695 // Setup ATI VBHard or std ptr.
696 switch(VB.VBMode)
698 #ifndef USE_OPENGLES
699 case CVertexBufferInfo::HwATI:
700 nglArrayObjectATI(GL_TEXTURE_COORD_ARRAY, numTexCoord, GL_FLOAT, VB.VertexSize, VB.VertexObjectId,
701 (ptrdiff_t) VB.ValuePtr[CVertexBuffer::TexCoord0+uvId]);
702 break;
703 #endif
704 case CVertexBufferInfo::HwARB:
705 _DriverGLStates.bindARBVertexBuffer(VB.VertexObjectId);
706 // with arb buffers, position is relative to the start of the stream
707 glTexCoordPointer(numTexCoord,GL_FLOAT,VB.VertexSize, VB.ValuePtr[CVertexBuffer::TexCoord0+uvId]);
708 break;
709 case CVertexBufferInfo::SysMem:
710 case CVertexBufferInfo::HwNVIDIA:
711 glTexCoordPointer(numTexCoord,GL_FLOAT,VB.VertexSize, VB.ValuePtr[CVertexBuffer::TexCoord0+uvId]);
712 break;
713 default:
714 break;
717 else
719 _DriverGLStates.enableTexCoordArray(false);
722 else
723 _DriverGLStates.enableTexCoordArray(false);
727 // ***************************************************************************
728 void CDriverGL::mapTextureStageToUV(uint stage, uint uv)
730 H_AUTO_OGL(CDriverGL_mapTextureStageToUV)
731 // Just call it for last VertexBuffer setuped.
732 setupUVPtr(stage, _LastVB, uv);
737 // ***************************************************************************
738 // ***************************************************************************
739 // VertexBufferHard
740 // ***************************************************************************
741 // ***************************************************************************
744 // ***************************************************************************
745 bool CDriverGL::supportVertexBufferHard() const
747 H_AUTO_OGL(CDriverGL_supportVertexBufferHard)
748 return _SupportVBHard;
751 // ***************************************************************************
752 bool CDriverGL::supportVolatileVertexBuffer() const
754 H_AUTO_OGL(CDriverGL_supportVolatileVertexBuffer)
755 return _Extensions.ARBMapBufferRange;
760 // ***************************************************************************
761 bool CDriverGL::slowUnlockVertexBufferHard() const
763 H_AUTO_OGL(CDriverGL_slowUnlockVertexBufferHard)
764 return _SlowUnlockVBHard;
768 // ***************************************************************************
769 uint CDriverGL::getMaxVerticesByVertexBufferHard() const
771 H_AUTO_OGL(CDriverGL_getMaxVerticesByVertexBufferHard)
772 return _MaxVerticesByVBHard;
776 // ***************************************************************************
777 IVertexBufferHardGL *CDriverGL::createVertexBufferHard(uint size, uint numVertices, CVertexBuffer::TPreferredMemory vbType, CVertexBuffer *vb)
779 H_AUTO_OGL(CDriverGL_createVertexBufferHard)
780 // choose the VertexArrayRange of good type
781 IVertexArrayRange *vertexArrayRange= NULL;
782 switch(vbType)
784 case CVertexBuffer::AGPVolatile:
785 case CVertexBuffer::AGPPreferred:
786 vertexArrayRange= _AGPVertexArrayRange;
787 break;
788 case CVertexBuffer::StaticPreferred:
789 if (getStaticMemoryToVRAM())
790 vertexArrayRange= _VRAMVertexArrayRange;
791 else
792 vertexArrayRange= _AGPVertexArrayRange;
793 break;
794 default:
795 break;
798 // If this one at least created (an extension support it).
799 if( !vertexArrayRange )
800 return NULL;
801 else
803 // check max vertex
804 if(numVertices > _MaxVerticesByVBHard)
805 return NULL;
807 // Create a CVertexBufferHardGL
808 IVertexBufferHardGL *vbHard = NULL;
809 // let the VAR create the vbhard.
810 vbHard= vertexArrayRange->createVBHardGL(size, vb);
811 // if fails
812 if(!vbHard)
814 return NULL;
816 else
818 // insert in list.
819 return _VertexBufferHardSet.insert(vbHard);
825 // ***************************************************************************
826 const uint CDriverGL::NumCoordinatesType[CVertexBuffer::NumType]=
828 1, // Double1
829 1, // Float1
830 1, // Short1
831 2, // Double2
832 2, // Float2
833 2, // Short2
834 3, // Double3
835 3, // Float3
836 3, // Short3
837 4, // Double4
838 4, // Float4
839 4, // Short4
840 4 // UChar4
844 // ***************************************************************************
845 const uint CDriverGL::GLType[CVertexBuffer::NumType]=
847 #ifdef USE_OPENGLES
848 GL_FLOAT, // Double1
849 GL_FLOAT, // Float1
850 GL_SHORT, // Short1
851 GL_FLOAT, // Double2
852 GL_FLOAT, // Float2
853 GL_SHORT, // Short2
854 GL_FLOAT, // Double3
855 GL_FLOAT, // Float3
856 GL_SHORT, // Short3
857 GL_FLOAT, // Double4
858 GL_FLOAT, // Float4
859 GL_SHORT, // Short4
860 GL_UNSIGNED_BYTE // UChar4
861 #else
862 GL_DOUBLE, // Double1
863 GL_FLOAT, // Float1
864 GL_SHORT, // Short1
865 GL_DOUBLE, // Double2
866 GL_FLOAT, // Float2
867 GL_SHORT, // Short2
868 GL_DOUBLE, // Double3
869 GL_FLOAT, // Float3
870 GL_SHORT, // Short3
871 GL_DOUBLE, // Double4
872 GL_FLOAT, // Float4
873 GL_SHORT, // Short4
874 GL_UNSIGNED_BYTE // UChar4
875 #endif
878 // ***************************************************************************
879 const bool CDriverGL::GLTypeIsIntegral[CVertexBuffer::NumType] =
881 false, // Double1
882 false, // Float1
883 true, // Short1
884 false, // Double2
885 false, // Float2
886 true, // Short2
887 false, // Double3
888 false, // Float3
889 true, // Short3
890 false, // Double4
891 false, // Float4
892 true, // Short4
893 true // UChar4
898 // ***************************************************************************
899 const uint CDriverGL::GLVertexAttribIndex[CVertexBuffer::NumValue]=
901 0, // Position
902 2, // Normal
903 8, // TexCoord0
904 9, // TexCoord1
905 10, // TexCoord2
906 11, // TexCoord3
907 12, // TexCoord4
908 13, // TexCoord5
909 14, // TexCoord6
910 15, // TexCoord7
911 3, // PrimaryColor
912 4, // SecondaryColor
913 1, // Weight
914 6, // Empty (PaletteSkin)
915 5, // Fog
916 7, // Empty
921 // ***************************************************************************
922 void CDriverGL::setupGlArraysStd(CVertexBufferInfo &vb)
924 H_AUTO_OGL(CDriverGL_setupGlArraysStd)
925 uint32 flags= vb.VertexFormat;
927 if (vb.VBMode == CVertexBufferInfo::HwARB)
929 _DriverGLStates.bindARBVertexBuffer(vb.VertexObjectId);
932 switch(vb.VBMode)
934 case CVertexBufferInfo::SysMem:
935 case CVertexBufferInfo::HwNVIDIA:
936 case CVertexBufferInfo::HwARB:
938 // setup vertex ptr.
939 //-----------
940 uint numVertexCoord = CVertexBuffer::NumComponentsType[vb.Type[CVertexBuffer::Position]];
941 nlassert (numVertexCoord >= 2);
942 _DriverGLStates.enableVertexArray(true);
943 glVertexPointer(numVertexCoord, GL_FLOAT, vb.VertexSize, vb.ValuePtr[CVertexBuffer::Position]);
945 // setup normal ptr.
946 //-----------
947 // Check for normal param in vertex buffer
948 if (flags & CVertexBuffer::NormalFlag)
950 // Check type
951 nlassert (vb.Type[CVertexBuffer::Normal]==CVertexBuffer::Float3);
953 _DriverGLStates.enableNormalArray(true);
954 glNormalPointer(GL_FLOAT, vb.VertexSize, vb.ValuePtr[CVertexBuffer::Normal]);
956 else
958 _DriverGLStates.enableNormalArray(false);
961 // Setup Color
962 //-----------
963 // Check for color param in vertex buffer
964 if (flags & CVertexBuffer::PrimaryColorFlag)
966 // Check type
967 nlassert (vb.Type[CVertexBuffer::PrimaryColor]==CVertexBuffer::UChar4);
968 _DriverGLStates.enableColorArray(true);
969 // Setup ATI VBHard or std ptr.
970 glColorPointer(4,GL_UNSIGNED_BYTE, vb.VertexSize, vb.ValuePtr[CVertexBuffer::PrimaryColor]);
972 else
974 _DriverGLStates.enableColorArray(false);
977 break;
978 #ifndef USE_OPENGLES
979 case CVertexBufferInfo::HwATI:
981 // setup vertex ptr.
982 //-----------
983 uint numVertexCoord = CVertexBuffer::NumComponentsType[vb.Type[CVertexBuffer::Position]];
984 nlassert (numVertexCoord >= 2);
986 _DriverGLStates.enableVertexArray(true);
987 nglArrayObjectATI(GL_VERTEX_ARRAY, numVertexCoord, GL_FLOAT, vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[CVertexBuffer::Position]);
988 // setup normal ptr.
989 //-----------
990 // Check for normal param in vertex buffer
991 if (flags & CVertexBuffer::NormalFlag)
993 // Check type
994 nlassert (vb.Type[CVertexBuffer::Normal]==CVertexBuffer::Float3);
995 _DriverGLStates.enableNormalArray(true);
996 nglArrayObjectATI(GL_NORMAL_ARRAY, 3, GL_FLOAT, vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[CVertexBuffer::Normal]);
998 else
1000 _DriverGLStates.enableNormalArray(false);
1004 // Setup Color
1005 //-----------
1006 // Check for color param in vertex buffer
1007 if (flags & CVertexBuffer::PrimaryColorFlag)
1009 // Check type
1010 nlassert (vb.Type[CVertexBuffer::PrimaryColor]==CVertexBuffer::UChar4);
1012 _DriverGLStates.enableColorArray(true);
1013 nglArrayObjectATI(GL_COLOR_ARRAY, 4, GL_UNSIGNED_BYTE, vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[CVertexBuffer::PrimaryColor]);
1015 else
1017 _DriverGLStates.enableColorArray(false);
1020 break;
1021 #endif
1022 default:
1023 nlassert(0);
1024 break;
1027 // Setup Uvs
1028 //-----------
1029 // Get the routing
1030 for(uint i=0; i<inlGetNumTextStages(); i++)
1032 // normal behavior: each texture has its own UV.
1033 setupUVPtr(i, vb, vb.UVRouting[i]);
1038 // ***************************************************************************
1039 void CDriverGL::toggleGlArraysForNVVertexProgram()
1041 H_AUTO_OGL(CDriverGL_toggleGlArraysForNVVertexProgram)
1042 // If change of setup type, must disable olds.
1043 //=======================
1045 // If last was a VertexProgram setup, and now it is a standard GL array setup.
1046 if( _LastSetupGLArrayVertexProgram && !isVertexProgramEnabled () )
1049 // Disable all VertexAttribs.
1050 for (uint value=0; value<CVertexBuffer::NumValue; value++)
1052 // Index
1053 uint glIndex=GLVertexAttribIndex[value];
1054 _DriverGLStates.enableVertexAttribArray(glIndex, false);
1056 _DriverGLStates.enableColorArray(false);
1057 _DriverGLStates.enableSecondaryColorArray(false);
1059 // no more a vertex program setup.
1060 _LastSetupGLArrayVertexProgram= false;
1063 // If last was a standard GL array setup, and now it is a VertexProgram setup.
1064 if( !_LastSetupGLArrayVertexProgram && isVertexProgramEnabled () )
1066 // Disable all standards ptrs.
1067 _DriverGLStates.enableVertexArray(false);
1068 _DriverGLStates.enableNormalArray(false);
1069 _DriverGLStates.enableColorArray(false);
1070 for(uint i=0; i<inlGetNumTextStages(); i++)
1072 _DriverGLStates.clientActiveTextureARB(i);
1073 _DriverGLStates.enableTexCoordArray(false);
1076 // now, vertex program setup.
1077 _LastSetupGLArrayVertexProgram= true;
1081 // ***************************************************************************
1082 void CDriverGL::toggleGlArraysForARBVertexProgram()
1084 H_AUTO_OGL(CDriverGL_toggleGlArraysForARBVertexProgram)
1085 // If change of setup type, must disable olds.
1086 //=======================
1088 // If last was a VertexProgram setup, and now it is a standard GL array setup.
1089 if( _LastSetupGLArrayVertexProgram && !isVertexProgramEnabled () )
1091 #ifndef USE_OPENGLES
1092 if (_Extensions.ATITextureEnvCombine3)
1093 #endif
1095 // fix for ATI : when switching from Vertex Program to fixed Pipe, must clean texture, otherwise texture may be disabled in next render
1096 // (seems to be a driver bug)
1097 ITexture *oldTex[IDRV_MAT_MAXTEXTURES];
1098 for(uint stage=0 ; stage < inlGetNumTextStages() ; stage++)
1100 oldTex[stage] = _CurrentTexture[stage];
1101 // activate the texture, or disable texturing if NULL.
1102 activateTexture(stage, NULL);
1105 #ifndef USE_OPENGLES
1106 glBegin(GL_QUADS);
1107 glVertex4f(0.f, 0.f, 0.f, 1.f);
1108 glVertex4f(0.f, 0.f, 0.f, 1.f);
1109 glVertex4f(0.f, 0.f, 0.f, 1.f);
1110 glVertex4f(0.f, 0.f, 0.f, 1.f);
1111 glEnd();
1112 #endif
1114 for(uint stage=0 ; stage<inlGetNumTextStages() ; stage++)
1116 // activate the texture, or disable texturing if NULL.
1117 activateTexture(stage, oldTex[stage]);
1121 // Disable all VertexAttribs.
1122 for (uint value=0; value<CVertexBuffer::NumValue; value++)
1124 // Index
1125 uint glIndex=GLVertexAttribIndex[value];
1126 _DriverGLStates.enableVertexAttribArrayARB(glIndex, false);
1128 // no more a vertex program setup.
1129 _LastSetupGLArrayVertexProgram= false;
1132 // If last was a standard GL array setup, and now it is a VertexProgram setup.
1133 if( !_LastSetupGLArrayVertexProgram && isVertexProgramEnabled () )
1135 // Disable all standards ptrs.
1136 _DriverGLStates.enableVertexArray(false);
1137 _DriverGLStates.enableNormalArray(false);
1138 _DriverGLStates.enableColorArray(false);
1139 _DriverGLStates.enableSecondaryColorArray(false);
1140 for(uint i=0; i<inlGetNumTextStages(); i++)
1142 _DriverGLStates.clientActiveTextureARB(i);
1143 _DriverGLStates.enableTexCoordArray(false);
1146 // now, vertex program setup.
1147 _LastSetupGLArrayVertexProgram= true;
1153 // ***************************************************************************
1154 void CDriverGL::toggleGlArraysForEXTVertexShader()
1156 H_AUTO_OGL(CDriverGL_toggleGlArraysForEXTVertexShader)
1157 // If change of setup type, must disable olds.
1158 //=======================
1161 // If last was a VertexProgram setup, and now it is a standard GL array setup.
1162 if( _LastSetupGLArrayVertexProgram && !isVertexProgramEnabled () )
1164 CVertexProgram *vp = _LastSetuppedVP;
1165 if (vp)
1167 CVertexProgamDrvInfosGL *drvInfo = NLMISC::safe_cast<CVertexProgamDrvInfosGL *>((IProgramDrvInfos *) vp->m_DrvInfo);
1168 if (drvInfo)
1170 // Disable all VertexAttribs.
1171 for (uint value=0; value<CVertexBuffer::NumValue; value++)
1173 _DriverGLStates.enableVertexAttribArrayForEXTVertexShader(value, false, drvInfo->Variants);
1177 // no more a vertex program setup.
1178 _LastSetupGLArrayVertexProgram= false;
1181 // If last was a standard GL array setup, and now it is a VertexProgram setup.
1182 if( !_LastSetupGLArrayVertexProgram && isVertexProgramEnabled () )
1184 // Disable all standards ptrs.
1185 _DriverGLStates.enableVertexArray(false);
1186 _DriverGLStates.enableNormalArray(false);
1187 _DriverGLStates.enableColorArray(false);
1188 _DriverGLStates.enableSecondaryColorArray(false);
1189 for(uint i=0; i<inlGetNumTextStages(); i++)
1191 _DriverGLStates.clientActiveTextureARB(i);
1192 _DriverGLStates.enableTexCoordArray(false);
1195 // now, vertex program setup.
1196 _LastSetupGLArrayVertexProgram= true;
1200 // ***************************************************************************
1201 void CDriverGL::setupGlArraysForNVVertexProgram(CVertexBufferInfo &vb)
1203 H_AUTO_OGL(CDriverGL_setupGlArraysForNVVertexProgram)
1204 uint16 flags= vb.VertexFormat;
1206 if (vb.VBMode == CVertexBufferInfo::HwARB)
1207 _DriverGLStates.bindARBVertexBuffer(vb.VertexObjectId);
1209 // For each value
1210 for (uint value=0; value<CVertexBuffer::NumValue; value++)
1212 //nldebug("3D: value = %d", value);
1213 // Flag
1214 uint16 flag=1<<value;
1216 // Type
1217 CVertexBuffer::TType type=vb.Type[value];
1219 // Index
1220 uint glIndex=GLVertexAttribIndex[value];
1222 // Not setuped value and used
1223 if (flags & flag)
1225 /* OpenGL Driver Bug with VertexProgram, UChar4 type, and VertexArrayRange.
1226 Don't work and lead to very poor performance (1/10) (VAR is "disabled").
1228 // Test if can use glColorPointer() / glSecondaryColorPointerEXT() instead.
1229 if( (glIndex==3 || glIndex==4) )
1231 if( type == CVertexBuffer::UChar4 )
1233 // Must disable VertexAttrib array.
1234 _DriverGLStates.enableVertexAttribArray(glIndex, false);
1236 // Active this value, with standard gl calls
1237 if(glIndex==3)
1239 // Primary color
1240 _DriverGLStates.enableColorArray(true);
1241 glColorPointer(4,GL_UNSIGNED_BYTE, vb.VertexSize, vb.ValuePtr[value]);
1243 else
1245 // Secondary color
1246 _DriverGLStates.enableSecondaryColorArray(true);
1247 #ifndef USE_OPENGLES
1248 nglSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, vb.VertexSize, vb.ValuePtr[value]);
1249 #endif
1252 else
1254 // Can use normal VertexAttribArray.
1255 // Disable first standard Color Array.
1256 if(glIndex==3)
1257 _DriverGLStates.enableColorArray(false);
1258 else
1259 _DriverGLStates.enableSecondaryColorArray(false);
1261 // Active this value
1262 _DriverGLStates.enableVertexAttribArray(glIndex, true);
1263 #ifndef USE_OPENGLES
1264 nglVertexAttribPointerNV (glIndex, NumCoordinatesType[type], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
1265 #endif
1268 // Else normal case, can't do anything for other values with UChar4....
1269 else
1271 // Active this value
1272 _DriverGLStates.enableVertexAttribArray(glIndex, true);
1273 #ifndef USE_OPENGLES
1274 nglVertexAttribPointerNV (glIndex, NumCoordinatesType[type], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
1275 #endif
1278 else
1280 _DriverGLStates.enableVertexAttribArray(glIndex, false);
1281 /* OpenGL Driver Bug with VertexProgram, UChar4 type, and VertexArrayRange.
1282 Must also disable colorArray in standard gl calls.
1284 if(glIndex==3)
1285 _DriverGLStates.enableColorArray(false);
1286 else if(glIndex==4)
1287 _DriverGLStates.enableSecondaryColorArray(false);
1291 if (vb.VBMode == CVertexBufferInfo::HwARB)
1292 _DriverGLStates.bindARBVertexBuffer(0);
1296 // tells for each vertex argument if it must be normalized when it is an integral type
1297 static const GLboolean ARBVertexProgramMustNormalizeAttrib[] =
1299 GL_FALSE, // Position
1300 GL_TRUE, // Normal
1301 GL_FALSE, // TexCoord0
1302 GL_FALSE, // TexCoord1
1303 GL_FALSE, // TexCoord2
1304 GL_FALSE, // TexCoord3
1305 GL_FALSE, // TexCoord4
1306 GL_FALSE, // TexCoord5
1307 GL_FALSE, // TexCoord6
1308 GL_FALSE, // TexCoord7
1309 GL_TRUE, // PrimaryColor
1310 GL_TRUE, // SecondaryColor
1311 GL_TRUE, // Weight
1312 GL_FALSE, // PaletteSkin
1313 GL_FALSE, // Fog
1314 GL_FALSE, // Empty
1317 // ***************************************************************************
1318 void CDriverGL::setupGlArraysForARBVertexProgram(CVertexBufferInfo &vb)
1320 H_AUTO_OGL(CDriverGL_setupGlArraysForARBVertexProgram)
1322 uint32 flags= vb.VertexFormat;
1324 nlctassert(CVertexBuffer::NumValue == sizeof(ARBVertexProgramMustNormalizeAttrib) / sizeof(ARBVertexProgramMustNormalizeAttrib[0]));
1326 if (vb.VBMode == CVertexBufferInfo::HwARB)
1328 _DriverGLStates.bindARBVertexBuffer(vb.VertexObjectId);
1331 #ifndef USE_OPENGLES
1332 // special case if the buffer is an ATI_vertex_array_object
1333 if (vb.VBMode == CVertexBufferInfo::HwATI)
1335 // For each value
1336 for (uint value=0; value<CVertexBuffer::NumValue; value++)
1338 // Flag
1339 uint16 flag=1<<value;
1341 // Type
1342 CVertexBuffer::TType type=vb.Type[value];
1344 // Index
1345 uint glIndex=GLVertexAttribIndex[value];
1346 // Not setuped value and used
1347 if (flags & flag)
1349 _DriverGLStates.enableVertexAttribArrayARB(glIndex, true);
1350 GLboolean mustNormalize = GL_FALSE;
1351 if (GLTypeIsIntegral[type])
1353 mustNormalize = ARBVertexProgramMustNormalizeAttrib[value];
1355 nglVertexAttribArrayObjectATI(glIndex, NumCoordinatesType[type], GLType[type], mustNormalize, vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[value]);
1357 else
1359 _DriverGLStates.enableVertexAttribArrayARB(glIndex, false);
1364 else
1365 #endif
1367 // For each value
1368 for (uint value=0; value<CVertexBuffer::NumValue; value++)
1370 // Flag
1371 uint16 flag=1<<value;
1373 // Type
1374 CVertexBuffer::TType type=vb.Type[value];
1376 // Index
1377 uint glIndex=GLVertexAttribIndex[value];
1378 // Not setuped value and used
1379 if (flags & flag)
1381 _DriverGLStates.enableVertexAttribArrayARB(glIndex, true);
1382 GLboolean mustNormalize = GL_FALSE;
1383 if (GLTypeIsIntegral[type])
1385 mustNormalize = ARBVertexProgramMustNormalizeAttrib[value];
1387 #ifdef USE_OPENGLES
1388 glVertexPointer(NumCoordinatesType[type], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
1389 #else
1390 nglVertexAttribPointerARB(glIndex, NumCoordinatesType[type], GLType[type], mustNormalize, vb.VertexSize, vb.ValuePtr[value]);
1391 #endif
1393 else
1395 _DriverGLStates.enableVertexAttribArrayARB(glIndex, false);
1404 // ***************************************************************************
1405 void CDriverGL::setupGlArraysForEXTVertexShader(CVertexBufferInfo &vb)
1407 H_AUTO_OGL(CDriverGL_setupGlArraysForEXTVertexShader)
1410 CVertexProgram *vp = _LastSetuppedVP;
1411 if (!vp) return;
1412 CVertexProgamDrvInfosGL *drvInfo = NLMISC::safe_cast<CVertexProgamDrvInfosGL *>((IProgramDrvInfos *) vp->m_DrvInfo);
1413 if (!drvInfo) return;
1415 uint32 flags= vb.VertexFormat;
1418 if (vb.VBMode == CVertexBufferInfo::HwARB)
1420 _DriverGLStates.bindARBVertexBuffer(vb.VertexObjectId);
1423 // For each value
1424 for (uint value=0; value<CVertexBuffer::NumValue; value++)
1426 // Flag
1427 uint16 flag=1<<value;
1429 // Type
1430 CVertexBuffer::TType type=vb.Type[value];
1432 // Index
1433 uint glIndex=GLVertexAttribIndex[value];
1435 // Not setuped value and used
1436 if (flags & flag & drvInfo->UsedVertexComponents)
1438 _DriverGLStates.enableVertexAttribArrayForEXTVertexShader(glIndex, true, drvInfo->Variants);
1439 #ifndef USE_OPENGLES
1440 // use variant or open gl standard array
1441 if (vb.VBMode == CVertexBufferInfo::HwATI)
1443 switch(value)
1445 case CVertexBuffer::Position: // position
1447 nlassert(NumCoordinatesType[type] >= 2);
1448 nglArrayObjectATI(GL_VERTEX_ARRAY, NumCoordinatesType[type], GLType[type], vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[CVertexBuffer::Position]);
1450 break;
1451 case CVertexBuffer::Weight: // skin weight
1453 nlassert(NumCoordinatesType[type] == 4); // variant, only 4 component supported
1454 nglVariantArrayObjectATI(drvInfo->Variants[CDriverGL::EVSSkinWeightVariant], GLType[type], vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[CVertexBuffer::Weight]);
1456 break;
1457 case CVertexBuffer::Normal: // normal
1459 nlassert(NumCoordinatesType[type] == 3); // must have 3 components for normals
1460 nglArrayObjectATI(GL_NORMAL_ARRAY, 3, GLType[type], vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[value]);
1462 break;
1463 case CVertexBuffer::PrimaryColor: // color
1465 nlassert(NumCoordinatesType[type] >= 3); // must have 3 or 4 components for primary color
1466 nglArrayObjectATI(GL_COLOR_ARRAY, NumCoordinatesType[type], GLType[type], vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[CVertexBuffer::PrimaryColor]);
1468 break;
1469 case CVertexBuffer::SecondaryColor: // secondary color
1471 // implemented using a variant, as not available with EXTVertexShader
1472 nlassert(NumCoordinatesType[type] == 4); // variant, only 4 component supported
1473 nglVariantArrayObjectATI(drvInfo->Variants[CDriverGL::EVSSecondaryColorVariant], GLType[type], vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[CVertexBuffer::SecondaryColor]);
1475 break;
1476 case CVertexBuffer::Fog: // fog coordinate
1478 // implemented using a variant
1479 nlassert(NumCoordinatesType[type] == 4); // variant, only 4 component supported
1480 nglVariantArrayObjectATI(drvInfo->Variants[CDriverGL::EVSFogCoordsVariant], GLType[type], vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[CVertexBuffer::Fog]);
1482 break;
1483 case CVertexBuffer::PaletteSkin: // palette skin
1485 // implemented using a variant
1486 nlassert(NumCoordinatesType[type] == 4); // variant, only 4 component supported
1487 nglVariantArrayObjectATI(drvInfo->Variants[CDriverGL::EVSPaletteSkinVariant], GLType[type], vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[CVertexBuffer::PaletteSkin]);
1489 break;
1490 case CVertexBuffer::Empty: // empty
1491 nlstop;
1492 break;
1493 case CVertexBuffer::TexCoord0:
1494 case CVertexBuffer::TexCoord1:
1495 case CVertexBuffer::TexCoord2:
1496 case CVertexBuffer::TexCoord3:
1497 case CVertexBuffer::TexCoord4:
1498 case CVertexBuffer::TexCoord5:
1499 case CVertexBuffer::TexCoord6:
1500 case CVertexBuffer::TexCoord7:
1502 _DriverGLStates.clientActiveTextureARB(value - CVertexBuffer::TexCoord0);
1503 nglArrayObjectATI(GL_TEXTURE_COORD_ARRAY, NumCoordinatesType[type], GLType[type], vb.VertexSize, vb.VertexObjectId, (ptrdiff_t) vb.ValuePtr[value]);
1505 break;
1506 default:
1507 nlstop; // invalid value
1508 break;
1511 else
1512 #endif
1514 switch(value)
1516 case CVertexBuffer::Position: // position
1518 nlassert(NumCoordinatesType[type] >= 2);
1519 glVertexPointer(NumCoordinatesType[type], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
1521 break;
1522 case CVertexBuffer::Weight: // skin weight
1524 nlassert(NumCoordinatesType[type] == 4); // variant, only 4 component supported
1525 #ifndef USE_OPENGLES
1526 nglVariantPointerEXT(drvInfo->Variants[CDriverGL::EVSSkinWeightVariant], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
1527 #endif
1529 break;
1530 case CVertexBuffer::Normal: // normal
1532 nlassert(NumCoordinatesType[type] == 3); // must have 3 components for normals
1533 glNormalPointer(GLType[type], vb.VertexSize, vb.ValuePtr[CVertexBuffer::Normal]);
1535 break;
1536 case CVertexBuffer::PrimaryColor: // color
1538 nlassert(NumCoordinatesType[type] >= 3); // must have 3 or 4 components for primary color
1539 glColorPointer(NumCoordinatesType[type], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
1541 break;
1542 case CVertexBuffer::SecondaryColor: // secondary color
1544 // implemented using a variant, as not available with EXTVertexShader
1545 nlassert(NumCoordinatesType[type] == 4); // variant, only 4 component supported
1546 #ifndef USE_OPENGLES
1547 nglVariantPointerEXT(drvInfo->Variants[CDriverGL::EVSSecondaryColorVariant], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
1548 #endif
1550 break;
1551 case CVertexBuffer::Fog: // fog coordinate
1553 // implemented using a variant
1554 nlassert(NumCoordinatesType[type] == 4); // variant, only 4 component supported
1555 #ifndef USE_OPENGLES
1556 nglVariantPointerEXT(drvInfo->Variants[CDriverGL::EVSFogCoordsVariant], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
1557 #endif
1559 break;
1560 case CVertexBuffer::PaletteSkin: // palette skin
1562 // implemented using a variant
1563 nlassert(NumCoordinatesType[type] == 4); // variant, only 4 component supported
1564 #ifndef USE_OPENGLES
1565 nglVariantPointerEXT(drvInfo->Variants[CDriverGL::EVSPaletteSkinVariant], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
1566 #endif
1568 break;
1569 case CVertexBuffer::Empty: // empty
1570 nlstop;
1571 break;
1572 case CVertexBuffer::TexCoord0:
1573 case CVertexBuffer::TexCoord1:
1574 case CVertexBuffer::TexCoord2:
1575 case CVertexBuffer::TexCoord3:
1576 case CVertexBuffer::TexCoord4:
1577 case CVertexBuffer::TexCoord5:
1578 case CVertexBuffer::TexCoord6:
1579 case CVertexBuffer::TexCoord7:
1581 _DriverGLStates.clientActiveTextureARB(value - CVertexBuffer::TexCoord0);
1582 glTexCoordPointer(NumCoordinatesType[type], GLType[type], vb.VertexSize, vb.ValuePtr[value]);
1584 break;
1585 default:
1586 nlstop; // invalid value
1587 break;
1591 else
1593 _DriverGLStates.enableVertexAttribArrayForEXTVertexShader(glIndex, false, drvInfo->Variants);
1600 // ***************************************************************************
1601 void CDriverGL::setupGlArrays(CVertexBufferInfo &vb)
1603 H_AUTO_OGL(CDriverGL_setupGlArrays)
1605 // Standard case (NVVertexProgram or no vertex program case)
1606 if (_Extensions.NVVertexProgram)
1608 toggleGlArraysForNVVertexProgram();
1609 // Use a vertex program ?
1610 if (!isVertexProgramEnabled ())
1612 setupGlArraysStd(vb);
1614 else
1616 setupGlArraysForNVVertexProgram(vb);
1619 else if (_Extensions.ARBVertexProgram)
1621 toggleGlArraysForARBVertexProgram();
1622 // Use a vertex program ?
1623 if (!isVertexProgramEnabled ())
1625 setupGlArraysStd(vb);
1627 else
1629 setupGlArraysForARBVertexProgram(vb);
1632 else if (_Extensions.EXTVertexShader)
1634 toggleGlArraysForEXTVertexShader();
1635 // Use a vertex program ?
1636 if (!isVertexProgramEnabled ())
1638 setupGlArraysStd(vb);
1640 else
1642 setupGlArraysForEXTVertexShader(vb);
1645 else
1647 // no vertex programs
1648 setupGlArraysStd(vb);
1653 // ***************************************************************************
1654 void CVertexBufferInfo::setupVertexBuffer(CVertexBuffer &vb)
1656 H_AUTO_OGL(CDriverGL_setupVertexBuffer)
1657 sint i;
1658 VertexFormat= vb.getVertexFormat();
1659 VertexSize= vb.getVertexSize();
1660 NumVertices= vb.getNumVertices();
1662 // Lock the buffer
1663 CVertexBufferReadWrite access;
1664 uint8 *ptr;
1665 CVBDrvInfosGL *info= safe_cast<CVBDrvInfosGL*>((IVBDrvInfos*)vb.DrvInfos);
1666 nlassert (info);
1667 if (info->_VBHard)
1669 ptr = (uint8*)info->_VBHard->getPointer();
1670 info->_VBHard->setupVBInfos(*this);
1672 else
1674 nlassert (info->_SystemMemory);
1675 ptr = info->_SystemMemory;
1676 VBMode = SysMem;
1679 // Get value pointer
1680 for (i=0; i<CVertexBuffer::NumValue; i++)
1682 // Value used ?
1683 if (VertexFormat&(1<<i))
1685 // Get the pointer
1686 ValuePtr[i]= ptr+vb.getValueOffEx((CVertexBuffer::TValue)i);
1688 // Type of the value
1689 Type[i]=vb.getValueType (i);
1693 // Copy the UVRouting table
1694 const uint8 *uvRouting = vb.getUVRouting();
1695 for (i=0; i<CVertexBuffer::MaxStage; i++)
1697 UVRouting[i] = uvRouting[i];
1702 // ***************************************************************************
1703 void CDriverGL::resetVertexArrayRange()
1705 H_AUTO_OGL(CDriverGL_resetVertexArrayRange)
1706 if(_CurrentVertexBufferHard)
1708 // Must ensure it has ended any drawing
1709 _CurrentVertexBufferHard->lock();
1710 _CurrentVertexBufferHard->unlock();
1711 // disable it
1712 _CurrentVertexBufferHard->disable();
1714 // Clear any VertexBufferHard created.
1715 _VertexBufferHardSet.clear();
1717 // After, Clear the 2 vertexArrayRange, if any.
1718 if(_AGPVertexArrayRange)
1719 _AGPVertexArrayRange->freeBlock();
1720 if(_VRAMVertexArrayRange)
1721 _VRAMVertexArrayRange->freeBlock();
1725 // ***************************************************************************
1726 bool CDriverGL::initVertexBufferHard(uint agpMem, uint vramMem)
1728 H_AUTO_OGL(CDriverGL_initVertexBufferHard)
1729 if(!supportVertexBufferHard())
1730 return false;
1732 // must be supported
1733 if(!_AGPVertexArrayRange || !_VRAMVertexArrayRange)
1734 return false;
1736 // First, reset any VBHard created.
1737 resetVertexArrayRange();
1738 bool ok= true;
1740 // Try to allocate AGPMemory.
1741 if(agpMem>0)
1743 agpMem&= ~15; // ensure 16-bytes aligned mem count (maybe useful :) ).
1744 agpMem= max(agpMem, (uint)NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE);
1745 while(agpMem>= NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE)
1747 if(_AGPVertexArrayRange->allocate(agpMem, CVertexBuffer::AGPPreferred))
1749 nlinfo("3D: %.u vertices supported", _MaxVerticesByVBHard);
1750 nlinfo("3D: Success to allocate %.1f Mo of AGP VAR Ram", agpMem / 1000000.f);
1751 break;
1753 else
1755 agpMem/=2;
1756 agpMem &=~15;
1760 if(agpMem< NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE)
1762 nlinfo("3D: %.u vertices supported", _MaxVerticesByVBHard);
1763 nlinfo("3D: Failed to allocate %.1f Mo of AGP VAR Ram", NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE / 1000000.f);
1764 ok= false;
1769 // Try to allocate VRAMMemory.
1770 if(vramMem>0)
1772 vramMem&= ~15; // ensure 16-bytes aligned mem count (maybe useful :) ).
1773 vramMem= max(vramMem, (uint)NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE);
1774 while(vramMem>= NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE)
1776 if(_VRAMVertexArrayRange->allocate(vramMem, CVertexBuffer::StaticPreferred))
1777 break;
1778 else
1780 vramMem/=2;
1781 vramMem &=~15;
1785 if(vramMem< NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE)
1787 ok= false;
1792 return ok;
1796 // ***************************************************************************
1797 uint32 CDriverGL::getAvailableVertexAGPMemory ()
1799 H_AUTO_OGL(CDriverGL_getAvailableVertexAGPMemory )
1800 if (_AGPVertexArrayRange)
1801 return _AGPVertexArrayRange->sizeAllocated();
1802 else
1803 return 0;
1807 // ***************************************************************************
1808 uint32 CDriverGL::getAvailableVertexVRAMMemory ()
1810 H_AUTO_OGL(CDriverGL_getAvailableVertexVRAMMemory )
1811 if (_VRAMVertexArrayRange)
1812 return _VRAMVertexArrayRange->sizeAllocated();
1813 else
1814 return 0;
1818 // ***************************************************************************
1819 void CDriverGL::fenceOnCurVBHardIfNeeded(IVertexBufferHardGL *newVBHard)
1821 H_AUTO_OGL(CDriverGL_fenceOnCurVBHardIfNeeded);
1823 #ifndef USE_OPENGLES
1824 // If old is not a VBHard, or if not a NVidia VBHard, no-op.
1825 if( _CurrentVertexBufferHard==NULL || _CurrentVertexBufferHard->VBType != IVertexBufferHardGL::NVidiaVB)
1826 return;
1828 // if we do not activate the same (NB: newVBHard==NULL if not a VBHard).
1829 if(_CurrentVertexBufferHard!=newVBHard)
1831 // get NVidia interface
1832 CVertexBufferHardGLNVidia *vbHardNV= static_cast<CVertexBufferHardGLNVidia*>(_CurrentVertexBufferHard);
1834 // If some render() have been done with this VB.
1835 if( vbHardNV->GPURenderingAfterFence )
1838 Since we won't work with this VB for a long time, we set a fence.
1840 NB: if the fence was previously set. NV_Fence Specification says that the new ONE replaces it.
1841 This is EXACTLY what we wants, since the old one is no more interesting.
1843 NB: never insert a fence for said "Static Lock" VBHard. Those VBHard are said to be "static"
1844 therefore, user should never modify them (else lock() is much slower...)
1846 if( !vbHardNV->getLockHintStatic() )
1847 vbHardNV->setFence();
1848 // Since we have set a new Fence, we won't need to do it at next vbHardNV->lock()
1849 vbHardNV->GPURenderingAfterFence= false;
1852 #endif
1855 // ***************************************************************************
1857 CIndexBufferInfo::CIndexBufferInfo()
1859 H_AUTO_OGL(CIndexBufferInfo_CIndexBufferInfo)
1860 _Values = NULL;
1863 // ***************************************************************************
1865 void CIndexBufferInfo::setupIndexBuffer(CIndexBuffer &ib)
1867 H_AUTO_OGL(CIndexBufferInfo_setupIndexBuffer)
1868 CIndexBufferReadWrite access;
1869 ib.lock (access);
1870 _Values = access.getPtr();
1871 _Format = access.getFormat();
1874 // ***************************************************************************
1876 #ifdef NL_STATIC
1877 } // NLDRIVERGL/ES
1878 #endif
1880 } // NL3D