1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013-2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
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"
30 using namespace NLMISC
;
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".
49 #define NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE (512*1024)
59 namespace NLDRIVERGLES
{
61 namespace NLDRIVERGL
{
65 // ***************************************************************************
67 CVBDrvInfosGL::CVBDrvInfosGL(CDriverGL
*drv
, ItVBDrvInfoPtrList it
, CVertexBuffer
*vb
) : IVBDrvInfos(drv
, it
, vb
)
69 H_AUTO_OGL(CVBDrvInfosGL_CVBDrvInfosGL
)
75 // ***************************************************************************
77 CVBDrvInfosGL::~CVBDrvInfosGL()
79 H_AUTO_OGL(CVBDrvInfosGL_CVBDrvInfosGLDtor
)
80 // Restore non resident memory
83 VertexBufferPtr
->setLocation(CVertexBuffer::NotResident
);
84 VertexBufferPtr
= NULL
;
90 _DriverGL
->_VertexBufferHardSet
.erase(_VBHard
);
94 delete [] _SystemMemory
;
100 // ***************************************************************************
101 uint8
*CVBDrvInfosGL::lock (uint
/* first */, uint
/* last */, bool /* readOnly */)
103 H_AUTO_OGL(CVBDrvInfosGL_lock
)
106 return (uint8
*)_VBHard
->lock ();
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
)
122 _VBHard
->unlock(first
, last
);
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
))
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
);
169 if ((CVertexBuffer::TPreferredMemory
)preferredMemory
== CVertexBuffer::AGPVolatile
)
171 preferredMemory
= CVertexBuffer::RAMPreferred
;
177 // No memory found ? Use system memory
178 if (info
->_VBHard
== NULL
)
180 nlassert (info
->_SystemMemory
== NULL
);
181 info
->_SystemMemory
= new uint8
[size
];
185 VB
.setLocation(preferredMemory
== CVertexBuffer::AGPVolatile
? CVertexBuffer::AGPResident
: (CVertexBuffer::TLocation
)preferredMemory
);
193 // ***************************************************************************
194 bool CDriverGL::activeVertexBuffer(CVertexBuffer
& VB
)
196 H_AUTO_OGL(CDriverGL_activeVertexBuffer
)
197 // NB: must duplicate changes in activeVertexBufferHard()
200 // In any case, we'll erase any special vertex setup for Lightmap Material
201 _LastVertexSetupIsLightMap
= false;
204 if (!setupVertexBuffer(VB
))
207 if (VB
.getNumVertices()==0)
210 // Fill the buffer if in local memory
213 // Get VB flags, to setup matrixes and arrays.
214 flags
=VB
.getVertexFormat();
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
)
233 fenceOnCurVBHardIfNeeded(NULL
);
235 // Disable the current vertexBufferHard if setuped.
236 if(_CurrentVertexBufferHard
)
237 _CurrentVertexBufferHard
->disable();
242 //===================
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
);
257 // ***************************************************************************
258 bool CDriverGL::activeIndexBuffer(CIndexBuffer
& IB
)
260 H_AUTO_OGL(CDriverGL_activeIndexBuffer
)
261 _LastIB
.setupIndexBuffer(IB
);
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();
274 if ( !setupMaterial(mat
) || _LastIB
._Values
== NULL
)
277 if (_CurrentVertexBufferHard
&& _CurrentVertexBufferHard
->isInvalid()) return true;
278 // render primitives.
279 //==============================
282 nPass
= beginMultiPass();
284 for(uint pass
=0;pass
<nPass
; pass
++)
288 // draw the primitives.
291 if (_LastIB
._Format
== CIndexBuffer::Indices16
)
293 glDrawElements(GL_LINES
,2*nlines
,GL_UNSIGNED_SHORT
,((uint16
*) _LastIB
._Values
)+firstIndex
);
298 nlerror("not available in OpenGL ES 1.0, only use 16 bits indices");
300 nlassert(_LastIB
._Format
== CIndexBuffer::Indices32
);
301 glDrawElements(GL_LINES
,2*nlines
,GL_UNSIGNED_INT
,((uint32
*) _LastIB
._Values
)+firstIndex
);
310 _PrimitiveProfileIn
.NLines
+= nlines
;
311 _PrimitiveProfileOut
.NLines
+= nlines
;
313 // We have render some prims. inform the VBHard.
314 if(_CurrentVertexBufferHard
)
315 _CurrentVertexBufferHard
->GPURenderingAfterFence
= 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();
330 if ( !setupMaterial(mat
) || _LastIB
._Values
== NULL
)
333 if (_CurrentVertexBufferHard
&& _CurrentVertexBufferHard
->isInvalid()) return true;
335 // render primitives.
336 //==============================
340 nPass
= beginMultiPass();
343 for(uint pass
=0;pass
<nPass
; pass
++)
348 // draw the primitives.
351 if (_LastIB
._Format
== CIndexBuffer::Indices16
)
353 glDrawElements(GL_TRIANGLES
,3*ntris
,GL_UNSIGNED_SHORT
, ((uint16
*) _LastIB
._Values
)+firstIndex
);
358 nlerror("not available in OpenGL ES 1.0, only use 16 bits indices");
360 nlassert(_LastIB
._Format
== CIndexBuffer::Indices32
);
361 glDrawElements(GL_TRIANGLES
,3*ntris
,GL_UNSIGNED_INT
, ((uint32
*) _LastIB
._Values
)+firstIndex
);
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;
380 // ***************************************************************************
382 bool CDriverGL::renderSimpleTriangles(uint32 firstTri
, uint32 ntris
)
384 H_AUTO_OGL(CDriverGL_renderSimpleTriangles
);
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
);
406 nlerror("not available in OpenGL ES 1.0, only use 16 bits indices");
408 nlassert(_LastIB
._Format
== CIndexBuffer::Indices32
);
409 glDrawElements(GL_TRIANGLES
,3*ntris
,GL_UNSIGNED_INT
, ((uint32
*) _LastIB
._Values
)+firstTri
);
414 _PrimitiveProfileIn
.NTriangles
+= ntris
;
415 _PrimitiveProfileOut
.NTriangles
+= ntris
;
417 // We have render some prims. inform the VBHard.
418 if(_CurrentVertexBufferHard
)
419 _CurrentVertexBufferHard
->GPURenderingAfterFence
= 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();
433 if ( !setupMaterial(mat
) )
436 if (_CurrentVertexBufferHard
&& _CurrentVertexBufferHard
->isInvalid()) return true;
437 // render primitives.
438 //==============================
441 nPass
= beginMultiPass();
443 for(uint pass
=0;pass
<nPass
; pass
++)
447 // draw the primitives.
449 glDrawArrays(GL_POINTS
, startIndex
, numPoints
);
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;
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();
474 if ( !setupMaterial(mat
) )
477 if (_CurrentVertexBufferHard
&& _CurrentVertexBufferHard
->isInvalid()) return true;
478 // render primitives.
479 //==============================
482 nPass
= beginMultiPass();
484 for(uint pass
=0;pass
<nPass
; pass
++)
488 // draw the primitives.
490 glDrawArrays(GL_LINES
, startIndex
<< 1, numLines
<< 1);
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;
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();
515 if ( !setupMaterial(mat
) )
518 if (_CurrentVertexBufferHard
&& _CurrentVertexBufferHard
->isInvalid()) return true;
519 // render primitives.
520 //==============================
523 nPass
= beginMultiPass();
525 for(uint pass
=0;pass
<nPass
; pass
++)
529 // draw the primitives.
532 glDrawArrays(GL_TRIANGLES
, startIndex
*3, numTris
*3);
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;
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();
559 if ( !setupMaterial(mat
) )
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;
569 // setup the base index buffer
570 for(uint k
= 0; k
< QUAD_BATCH_SIZE
; ++k
)
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);
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);
585 // render primitives.
586 //==============================
589 nPass
= beginMultiPass();
591 for(uint pass
=0;pass
<nPass
; 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
612 // TODO : resetting vertex pointer would avoid the need to rebuild indices each times
613 uint32 numQuadsToDraw
= std::min(numLeftQuads
, QUAD_BATCH_SIZE
);
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;
633 glDrawElements(GL_TRIANGLES
, 6 * numQuadsToDraw
, GL_UNSIGNED_SHORT
, indices
);
638 nlerror("not available in OpenGL ES 1.0, only use 16 bits indices");
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;
656 glDrawElements(GL_TRIANGLES
, 6 * numQuadsToDraw
, GL_UNSIGNED_INT
, indices
);
659 numLeftQuads
-= numQuadsToDraw
;
660 currIndex
+= 4 * numQuadsToDraw
;
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;
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.
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
]);
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
]);
709 case CVertexBufferInfo::SysMem
:
710 case CVertexBufferInfo::HwNVIDIA
:
711 glTexCoordPointer(numTexCoord
,GL_FLOAT
,VB
.VertexSize
, VB
.ValuePtr
[CVertexBuffer::TexCoord0
+uvId
]);
719 _DriverGLStates
.enableTexCoordArray(false);
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 // ***************************************************************************
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
;
784 case CVertexBuffer::AGPVolatile
:
785 case CVertexBuffer::AGPPreferred
:
786 vertexArrayRange
= _AGPVertexArrayRange
;
788 case CVertexBuffer::StaticPreferred
:
789 if (getStaticMemoryToVRAM())
790 vertexArrayRange
= _VRAMVertexArrayRange
;
792 vertexArrayRange
= _AGPVertexArrayRange
;
798 // If this one at least created (an extension support it).
799 if( !vertexArrayRange
)
804 if(numVertices
> _MaxVerticesByVBHard
)
807 // Create a CVertexBufferHardGL
808 IVertexBufferHardGL
*vbHard
= NULL
;
809 // let the VAR create the vbhard.
810 vbHard
= vertexArrayRange
->createVBHardGL(size
, vb
);
819 return _VertexBufferHardSet
.insert(vbHard
);
825 // ***************************************************************************
826 const uint
CDriverGL::NumCoordinatesType
[CVertexBuffer::NumType
]=
844 // ***************************************************************************
845 const uint
CDriverGL::GLType
[CVertexBuffer::NumType
]=
860 GL_UNSIGNED_BYTE
// UChar4
862 GL_DOUBLE
, // Double1
865 GL_DOUBLE
, // Double2
868 GL_DOUBLE
, // Double3
871 GL_DOUBLE
, // Double4
874 GL_UNSIGNED_BYTE
// UChar4
878 // ***************************************************************************
879 const bool CDriverGL::GLTypeIsIntegral
[CVertexBuffer::NumType
] =
898 // ***************************************************************************
899 const uint
CDriverGL::GLVertexAttribIndex
[CVertexBuffer::NumValue
]=
914 6, // Empty (PaletteSkin)
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
);
934 case CVertexBufferInfo::SysMem
:
935 case CVertexBufferInfo::HwNVIDIA
:
936 case CVertexBufferInfo::HwARB
:
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
]);
947 // Check for normal param in vertex buffer
948 if (flags
& CVertexBuffer::NormalFlag
)
951 nlassert (vb
.Type
[CVertexBuffer::Normal
]==CVertexBuffer::Float3
);
953 _DriverGLStates
.enableNormalArray(true);
954 glNormalPointer(GL_FLOAT
, vb
.VertexSize
, vb
.ValuePtr
[CVertexBuffer::Normal
]);
958 _DriverGLStates
.enableNormalArray(false);
963 // Check for color param in vertex buffer
964 if (flags
& CVertexBuffer::PrimaryColorFlag
)
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
]);
974 _DriverGLStates
.enableColorArray(false);
979 case CVertexBufferInfo::HwATI
:
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
]);
990 // Check for normal param in vertex buffer
991 if (flags
& CVertexBuffer::NormalFlag
)
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
]);
1000 _DriverGLStates
.enableNormalArray(false);
1006 // Check for color param in vertex buffer
1007 if (flags
& CVertexBuffer::PrimaryColorFlag
)
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
]);
1017 _DriverGLStates
.enableColorArray(false);
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
++)
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
)
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
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
);
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
++)
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
;
1167 CVertexProgamDrvInfosGL
*drvInfo
= NLMISC::safe_cast
<CVertexProgamDrvInfosGL
*>((IProgramDrvInfos
*) vp
->m_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
);
1210 for (uint value
=0; value
<CVertexBuffer::NumValue
; value
++)
1212 //nldebug("3D: value = %d", value);
1214 uint16 flag
=1<<value
;
1217 CVertexBuffer::TType type
=vb
.Type
[value
];
1220 uint glIndex
=GLVertexAttribIndex
[value
];
1222 // Not setuped value and used
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
1240 _DriverGLStates
.enableColorArray(true);
1241 glColorPointer(4,GL_UNSIGNED_BYTE
, vb
.VertexSize
, vb
.ValuePtr
[value
]);
1246 _DriverGLStates
.enableSecondaryColorArray(true);
1247 #ifndef USE_OPENGLES
1248 nglSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE
, vb
.VertexSize
, vb
.ValuePtr
[value
]);
1254 // Can use normal VertexAttribArray.
1255 // Disable first standard Color Array.
1257 _DriverGLStates
.enableColorArray(false);
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
]);
1268 // Else normal case, can't do anything for other values with UChar4....
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
]);
1280 _DriverGLStates
.enableVertexAttribArray(glIndex
, false);
1281 /* OpenGL Driver Bug with VertexProgram, UChar4 type, and VertexArrayRange.
1282 Must also disable colorArray in standard gl calls.
1285 _DriverGLStates
.enableColorArray(false);
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
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
1312 GL_FALSE
, // PaletteSkin
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
)
1336 for (uint value
=0; value
<CVertexBuffer::NumValue
; value
++)
1339 uint16 flag
=1<<value
;
1342 CVertexBuffer::TType type
=vb
.Type
[value
];
1345 uint glIndex
=GLVertexAttribIndex
[value
];
1346 // Not setuped value and used
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
]);
1359 _DriverGLStates
.enableVertexAttribArrayARB(glIndex
, false);
1368 for (uint value
=0; value
<CVertexBuffer::NumValue
; value
++)
1371 uint16 flag
=1<<value
;
1374 CVertexBuffer::TType type
=vb
.Type
[value
];
1377 uint glIndex
=GLVertexAttribIndex
[value
];
1378 // Not setuped value and used
1381 _DriverGLStates
.enableVertexAttribArrayARB(glIndex
, true);
1382 GLboolean mustNormalize
= GL_FALSE
;
1383 if (GLTypeIsIntegral
[type
])
1385 mustNormalize
= ARBVertexProgramMustNormalizeAttrib
[value
];
1388 glVertexPointer(NumCoordinatesType
[type
], GLType
[type
], vb
.VertexSize
, vb
.ValuePtr
[value
]);
1390 nglVertexAttribPointerARB(glIndex
, NumCoordinatesType
[type
], GLType
[type
], mustNormalize
, vb
.VertexSize
, vb
.ValuePtr
[value
]);
1395 _DriverGLStates
.enableVertexAttribArrayARB(glIndex
, false);
1404 // ***************************************************************************
1405 void CDriverGL::setupGlArraysForEXTVertexShader(CVertexBufferInfo
&vb
)
1407 H_AUTO_OGL(CDriverGL_setupGlArraysForEXTVertexShader
)
1410 CVertexProgram
*vp
= _LastSetuppedVP
;
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
);
1424 for (uint value
=0; value
<CVertexBuffer::NumValue
; value
++)
1427 uint16 flag
=1<<value
;
1430 CVertexBuffer::TType type
=vb
.Type
[value
];
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
)
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
]);
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
]);
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
]);
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
]);
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
]);
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
]);
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
]);
1490 case CVertexBuffer::Empty
: // empty
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
]);
1507 nlstop
; // invalid value
1516 case CVertexBuffer::Position
: // position
1518 nlassert(NumCoordinatesType
[type
] >= 2);
1519 glVertexPointer(NumCoordinatesType
[type
], GLType
[type
], vb
.VertexSize
, vb
.ValuePtr
[value
]);
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
]);
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
]);
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
]);
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
]);
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
]);
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
]);
1569 case CVertexBuffer::Empty
: // empty
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
]);
1586 nlstop
; // invalid value
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
);
1616 setupGlArraysForNVVertexProgram(vb
);
1619 else if (_Extensions
.ARBVertexProgram
)
1621 toggleGlArraysForARBVertexProgram();
1622 // Use a vertex program ?
1623 if (!isVertexProgramEnabled ())
1625 setupGlArraysStd(vb
);
1629 setupGlArraysForARBVertexProgram(vb
);
1632 else if (_Extensions
.EXTVertexShader
)
1634 toggleGlArraysForEXTVertexShader();
1635 // Use a vertex program ?
1636 if (!isVertexProgramEnabled ())
1638 setupGlArraysStd(vb
);
1642 setupGlArraysForEXTVertexShader(vb
);
1647 // no vertex programs
1648 setupGlArraysStd(vb
);
1653 // ***************************************************************************
1654 void CVertexBufferInfo::setupVertexBuffer(CVertexBuffer
&vb
)
1656 H_AUTO_OGL(CDriverGL_setupVertexBuffer
)
1658 VertexFormat
= vb
.getVertexFormat();
1659 VertexSize
= vb
.getVertexSize();
1660 NumVertices
= vb
.getNumVertices();
1663 CVertexBufferReadWrite access
;
1665 CVBDrvInfosGL
*info
= safe_cast
<CVBDrvInfosGL
*>((IVBDrvInfos
*)vb
.DrvInfos
);
1669 ptr
= (uint8
*)info
->_VBHard
->getPointer();
1670 info
->_VBHard
->setupVBInfos(*this);
1674 nlassert (info
->_SystemMemory
);
1675 ptr
= info
->_SystemMemory
;
1679 // Get value pointer
1680 for (i
=0; i
<CVertexBuffer::NumValue
; i
++)
1683 if (VertexFormat
&(1<<i
))
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();
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())
1732 // must be supported
1733 if(!_AGPVertexArrayRange
|| !_VRAMVertexArrayRange
)
1736 // First, reset any VBHard created.
1737 resetVertexArrayRange();
1740 // Try to allocate AGPMemory.
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
);
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
);
1769 // Try to allocate VRAMMemory.
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
))
1785 if(vramMem
< NL3D_DRV_VERTEXARRAY_MINIMUM_SIZE
)
1796 // ***************************************************************************
1797 uint32
CDriverGL::getAvailableVertexAGPMemory ()
1799 H_AUTO_OGL(CDriverGL_getAvailableVertexAGPMemory
)
1800 if (_AGPVertexArrayRange
)
1801 return _AGPVertexArrayRange
->sizeAllocated();
1807 // ***************************************************************************
1808 uint32
CDriverGL::getAvailableVertexVRAMMemory ()
1810 H_AUTO_OGL(CDriverGL_getAvailableVertexVRAMMemory
)
1811 if (_VRAMVertexArrayRange
)
1812 return _VRAMVertexArrayRange
->sizeAllocated();
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
)
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;
1855 // ***************************************************************************
1857 CIndexBufferInfo::CIndexBufferInfo()
1859 H_AUTO_OGL(CIndexBufferInfo_CIndexBufferInfo
)
1863 // ***************************************************************************
1865 void CIndexBufferInfo::setupIndexBuffer(CIndexBuffer
&ib
)
1867 H_AUTO_OGL(CIndexBufferInfo_setupIndexBuffer
)
1868 CIndexBufferReadWrite access
;
1870 _Values
= access
.getPtr();
1871 _Format
= access
.getFormat();
1874 // ***************************************************************************