0026122: Visualization, TKOpenGl - clipping and capping is broken when ffp is disable...
[occt.git] / src / OpenGl / OpenGl_PrimitiveArray.cxx
CommitLineData
b311480e 1// Created on: 2011-07-13
2// Created by: Sergey ZERCHANINOV
de75ed09 3// Copyright (c) 2011-2013 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
b311480e 15
2166f0fa 16#include <OpenGl_AspectFace.hxx>
30f0ad28 17#include <OpenGl_Context.hxx>
2166f0fa 18#include <OpenGl_GraphicDriver.hxx>
30f0ad28 19#include <OpenGl_IndexBuffer.hxx>
a577aaab 20#include <OpenGl_PointSprite.hxx>
30f0ad28 21#include <OpenGl_PrimitiveArray.hxx>
22#include <OpenGl_ShaderManager.hxx>
23#include <OpenGl_ShaderProgram.hxx>
2166f0fa 24#include <OpenGl_Structure.hxx>
7d3e64ef 25#include <OpenGl_VertexBufferCompat.hxx>
bf75be98 26#include <OpenGl_Workspace.hxx>
6c6aadb1 27#include <Graphic3d_TextureParams.hxx>
e99a2f7c 28#include <NCollection_AlignedAllocator.hxx>
2166f0fa 29
30f0ad28 30namespace
31{
871fa103 32 //! Convert data type to GL info
33 inline GLenum toGlDataType (const Graphic3d_TypeOfData theType,
34 GLint& theNbComp)
35 {
36 switch (theType)
37 {
38 case Graphic3d_TOD_USHORT:
39 theNbComp = 1;
40 return GL_UNSIGNED_SHORT;
41 case Graphic3d_TOD_UINT:
42 theNbComp = 1;
43 return GL_UNSIGNED_INT;
44 case Graphic3d_TOD_VEC2:
45 theNbComp = 2;
46 return GL_FLOAT;
47 case Graphic3d_TOD_VEC3:
48 theNbComp = 3;
49 return GL_FLOAT;
50 case Graphic3d_TOD_VEC4:
51 theNbComp = 4;
52 return GL_FLOAT;
53 case Graphic3d_TOD_VEC4UB:
54 theNbComp = 4;
55 return GL_UNSIGNED_BYTE;
56 }
57 theNbComp = 0;
58 return GL_NONE;
59 }
60
30f0ad28 61}
62
871fa103 63//! Auxiliary template for VBO with interleaved attributes.
7d3e64ef 64template<class TheBaseClass, int NbAttributes>
65class OpenGl_VertexBufferT : public TheBaseClass
7fd59977 66{
871fa103 67
68public:
69
70 //! Create uninitialized VBO.
71 OpenGl_VertexBufferT (const Graphic3d_Attribute* theAttribs,
72 const Standard_Integer theStride)
73 : Stride (theStride)
74 {
75 memcpy (Attribs, theAttribs, sizeof(Graphic3d_Attribute) * NbAttributes);
76 }
77
78 //! Create uninitialized VBO.
79 OpenGl_VertexBufferT (const Graphic3d_Buffer& theAttribs)
80 : Stride (theAttribs.Stride)
81 {
82 memcpy (Attribs, theAttribs.AttributesArray(), sizeof(Graphic3d_Attribute) * NbAttributes);
83 }
84
85 virtual bool HasColorAttribute() const
86 {
87 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
88 {
89 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
90 if (anAttrib.Id == Graphic3d_TOA_COLOR)
91 {
92 return true;
93 }
94 }
95 return false;
96 }
97
7d3e64ef 98 virtual bool HasNormalAttribute() const
99 {
100 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
101 {
102 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
103 if (anAttrib.Id == Graphic3d_TOA_NORM)
104 {
105 return true;
106 }
107 }
108 return false;
109 }
110
111 virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const
871fa103 112 {
7d3e64ef 113 if (!TheBaseClass::IsValid())
871fa103 114 {
115 return;
116 }
117
7d3e64ef 118 TheBaseClass::Bind (theGlCtx);
871fa103 119 GLint aNbComp;
7d3e64ef 120 const GLubyte* anOffset = TheBaseClass::myOffset;
871fa103 121 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
122 {
123 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
124 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
125 if (aDataType == GL_NONE)
126 {
127 continue;
128 }
129 else if (anAttrib.Id == Graphic3d_TOA_POS)
130 {
7d3e64ef 131 TheBaseClass::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
871fa103 132 break;
133 }
134
135 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
136 }
137 }
138
7d3e64ef 139 virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
871fa103 140 {
7d3e64ef 141 if (!TheBaseClass::IsValid())
871fa103 142 {
143 return;
144 }
145
7d3e64ef 146 TheBaseClass::Bind (theGlCtx);
871fa103 147 GLint aNbComp;
7d3e64ef 148 const GLubyte* anOffset = TheBaseClass::myOffset;
871fa103 149 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
150 {
151 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
152 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
153 if (aDataType == GL_NONE)
154 {
155 continue;
156 }
157
7d3e64ef 158 TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
871fa103 159 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
160 }
161 }
162
7d3e64ef 163 virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
871fa103 164 {
7d3e64ef 165 if (!TheBaseClass::IsValid())
871fa103 166 {
167 return;
168 }
7d3e64ef 169 TheBaseClass::Unbind (theGlCtx);
871fa103 170
171 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
172 {
173 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
7d3e64ef 174 TheBaseClass::unbindAttribute (theGlCtx, anAttrib.Id);
871fa103 175 }
176 }
177
178public:
179
180 Graphic3d_Attribute Attribs[NbAttributes];
181 Standard_Integer Stride;
182
183};
7fd59977 184
2166f0fa
SK
185// =======================================================================
186// function : clearMemoryGL
187// purpose :
188// =======================================================================
5e27df78 189void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
7fd59977 190{
871fa103 191 if (!myVboIndices.IsNull())
2166f0fa 192 {
871fa103 193 myVboIndices->Release (theGlCtx.operator->());
194 myVboIndices.Nullify();
195 }
196 if (!myVboAttribs.IsNull())
197 {
198 myVboAttribs->Release (theGlCtx.operator->());
199 myVboAttribs.Nullify();
2166f0fa 200 }
7fd59977 201}
202
2166f0fa 203// =======================================================================
7d3e64ef 204// function : initNormalVbo
2166f0fa
SK
205// purpose :
206// =======================================================================
7d3e64ef 207Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Context)& theCtx) const
7fd59977 208{
7d3e64ef 209 switch (myAttribs->NbAttributes)
2166f0fa 210 {
7d3e64ef 211 case 1: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 1> (*myAttribs); break;
212 case 2: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 2> (*myAttribs); break;
213 case 3: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 3> (*myAttribs); break;
214 case 4: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 4> (*myAttribs); break;
215 case 5: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 5> (*myAttribs); break;
216 case 6: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 6> (*myAttribs); break;
217 case 7: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 7> (*myAttribs); break;
218 case 8: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 8> (*myAttribs); break;
219 case 9: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 9> (*myAttribs); break;
220 case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break;
221 }
222
223 if (!myVboAttribs->init (theCtx, 0, myAttribs->NbElements, myAttribs->Data(), GL_NONE, myAttribs->Stride))
224 {
225 TCollection_ExtendedString aMsg;
226 aMsg += "VBO creation for Primitive Array has failed for ";
227 aMsg += myAttribs->NbElements;
228 aMsg += " vertices. Out of memory?";
229 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
230
231 clearMemoryGL (theCtx);
5e27df78 232 return Standard_False;
2166f0fa 233 }
7d3e64ef 234 else if (myIndices.IsNull())
235 {
236 return Standard_True;
237 }
7fd59977 238
7d3e64ef 239 myVboIndices = new OpenGl_IndexBuffer();
240 bool isOk = false;
241 switch (myIndices->Stride)
242 {
243 case 2:
244 {
245 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLushort*> (myIndices->Data()));
246 break;
247 }
248 case 4:
249 {
250 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLuint*> (myIndices->Data()));
251 break;
252 }
253 default:
254 {
255 clearMemoryGL (theCtx);
256 return Standard_False;
257 }
258 }
259 if (!isOk)
2166f0fa 260 {
7d3e64ef 261 TCollection_ExtendedString aMsg;
262 aMsg += "VBO creation for Primitive Array has failed for ";
263 aMsg += myIndices->NbElements;
264 aMsg += " indices. Out of memory?";
265 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
266 clearMemoryGL (theCtx);
267 return Standard_False;
7fd59977 268 }
7d3e64ef 269 return Standard_True;
270}
871fa103 271
7d3e64ef 272// =======================================================================
273// function : buildVBO
274// purpose :
275// =======================================================================
276Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& theCtx,
277 const Standard_Boolean theToKeepData) const
278{
279 bool isNormalMode = theCtx->ToUseVbo();
536d98e2 280 clearMemoryGL (theCtx);
7d3e64ef 281 if (myAttribs.IsNull()
282 || myAttribs->IsEmpty()
283 || myAttribs->NbElements < 1
284 || myAttribs->NbAttributes < 1
285 || myAttribs->NbAttributes > 10)
2166f0fa 286 {
7d3e64ef 287 // vertices should be always defined - others are optional
871fa103 288 return Standard_False;
7fd59977 289 }
871fa103 290
7d3e64ef 291 if (isNormalMode
292 && initNormalVbo (theCtx))
293 {
294 if (!theCtx->caps->keepArrayData
295 && !theToKeepData)
296 {
297 myIndices.Nullify();
298 myAttribs.Nullify();
299 }
300 return Standard_True;
301 }
302
303 Handle(OpenGl_VertexBufferCompat) aVboAttribs;
304 switch (myAttribs->NbAttributes)
305 {
306 case 1: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 1> (*myAttribs); break;
307 case 2: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 2> (*myAttribs); break;
308 case 3: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 3> (*myAttribs); break;
309 case 4: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 4> (*myAttribs); break;
310 case 5: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 5> (*myAttribs); break;
311 case 6: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 6> (*myAttribs); break;
312 case 7: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 7> (*myAttribs); break;
313 case 8: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 8> (*myAttribs); break;
314 case 9: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 9> (*myAttribs); break;
315 case 10: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 10>(*myAttribs); break;
316 }
317 aVboAttribs->initLink (myAttribs, 0, myAttribs->NbElements, GL_NONE);
871fa103 318 if (!myIndices.IsNull())
2166f0fa 319 {
7d3e64ef 320 Handle(OpenGl_VertexBufferCompat) aVboIndices = new OpenGl_VertexBufferCompat();
871fa103 321 switch (myIndices->Stride)
5e27df78 322 {
871fa103 323 case 2:
324 {
7d3e64ef 325 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_SHORT);
871fa103 326 break;
327 }
328 case 4:
329 {
7d3e64ef 330 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_INT);
871fa103 331 break;
332 }
7d3e64ef 333 default:
334 {
335 return Standard_False;
336 }
5e27df78 337 }
7d3e64ef 338 myVboIndices = aVboIndices;
2166f0fa 339 }
7d3e64ef 340 myVboAttribs = aVboAttribs;
341 if (!theCtx->caps->keepArrayData
342 && !theToKeepData)
e276548b 343 {
7d3e64ef 344 // does not make sense for compatibility mode
345 //myIndices.Nullify();
346 //myAttribs.Nullify();
e276548b 347 }
7d3e64ef 348
2166f0fa 349 return Standard_True;
7fd59977 350}
351
2166f0fa 352// =======================================================================
7d3e64ef 353// function : drawArray
2166f0fa
SK
354// purpose :
355// =======================================================================
7d3e64ef 356void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorkspace,
8625ef7e 357 const Graphic3d_Vec4* theFaceColors,
358 const Standard_Boolean theHasVertColor) const
7fd59977 359{
871fa103 360 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
871fa103 361 const bool toHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0;
8625ef7e 362 bool hasVColors = theHasVertColor && !toHilight;
7d3e64ef 363 if (myVboAttribs.IsNull())
2166f0fa 364 {
ca3c13d1 365 #if !defined(GL_ES_VERSION_2_0)
7d3e64ef 366 if (myDrawMode == GL_POINTS)
367 {
368 // extreme compatibility mode - without sprites but with markers
369 drawMarkers (theWorkspace);
370 }
ca3c13d1 371 #endif
7d3e64ef 372 return;
7fd59977 373 }
374
7d3e64ef 375 myVboAttribs->BindAllAttributes (aGlContext);
8625ef7e 376 if (theHasVertColor && toHilight)
2166f0fa 377 {
8625ef7e 378 // disable per-vertex color
379 OpenGl_VertexBuffer::unbindAttribute (aGlContext, Graphic3d_TOA_COLOR);
7d3e64ef 380 }
381 if (!myVboIndices.IsNull())
382 {
383 myVboIndices->Bind (aGlContext);
384 GLubyte* anOffset = myVboIndices->GetDataOffset();
385 if (!myBounds.IsNull())
2166f0fa 386 {
7d3e64ef 387 // draw primitives by vertex count with the indices
388 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
389 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
2166f0fa 390 {
7d3e64ef 391 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
8625ef7e 392 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
7d3e64ef 393 glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
394 anOffset += aStride * aNbElemsInGroup;
762aacae 395 }
bf75be98 396 }
2166f0fa
SK
397 else
398 {
7d3e64ef 399 // draw one (or sequential) primitive by the indices
400 glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
5e27df78 401 }
7d3e64ef 402 myVboIndices->Unbind (aGlContext);
7fd59977 403 }
7d3e64ef 404 else if (!myBounds.IsNull())
871fa103 405 {
7d3e64ef 406 GLint aFirstElem = 0;
407 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
408 {
409 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
8625ef7e 410 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
7d3e64ef 411 glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
412 aFirstElem += aNbElemsInGroup;
413 }
871fa103 414 }
7d3e64ef 415 else
2166f0fa 416 {
7d3e64ef 417 if (myDrawMode == GL_POINTS)
418 {
419 drawMarkers (theWorkspace);
420 }
421 else
422 {
423 glDrawArrays (myDrawMode, 0, myVboAttribs->GetElemsNb());
424 }
2166f0fa
SK
425 }
426
7d3e64ef 427 // bind with 0
428 myVboAttribs->UnbindAllAttributes (aGlContext);
429
430 if (hasVColors)
431 {
432 theWorkspace->NamedStatus |= OPENGL_NS_RESMAT;
433 }
7fd59977 434}
435
2166f0fa 436// =======================================================================
7d3e64ef 437// function : drawEdges
2166f0fa
SK
438// purpose :
439// =======================================================================
7d3e64ef 440void OpenGl_PrimitiveArray::drawEdges (const TEL_COLOUR* theEdgeColour,
2166f0fa 441 const Handle(OpenGl_Workspace)& theWorkspace) const
7fd59977 442{
65360da3 443 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
7d3e64ef 444 if (myVboAttribs.IsNull())
445 {
446 return;
447 }
448
ca3c13d1 449#if !defined(GL_ES_VERSION_2_0)
65360da3 450 if (aGlContext->core11 != NULL)
451 {
452 glDisable (GL_LIGHTING);
453 }
ca3c13d1 454#endif
7fd59977 455
2166f0fa 456 const OpenGl_AspectLine* anAspectLineOld = NULL;
7fd59977 457
7d3e64ef 458 anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge());
459 const OpenGl_AspectLine* anAspect = theWorkspace->AspectLine (Standard_True);
30f0ad28 460
ca3c13d1 461#if !defined(GL_ES_VERSION_2_0)
7d3e64ef 462 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
ca3c13d1 463#endif
7d3e64ef 464
4e1523ef 465 if (aGlContext->core20fwd != NULL)
7d3e64ef 466 {
8625ef7e 467 aGlContext->ShaderManager()->BindProgram (anAspect, NULL, Standard_False, Standard_False, anAspect->ShaderProgramRes (aGlContext));
2166f0fa 468 }
7fd59977 469
5e27df78 470 /// OCC22236 NOTE: draw edges for all situations:
871fa103 471 /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indices array
472 /// 2) draw elements from vertex array, when bounds defines count of primitive's vertices.
5e27df78 473 /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
7d3e64ef 474 myVboAttribs->BindPositionAttribute (aGlContext);
ac116c22 475
476 aGlContext->SetColor4fv (*(const OpenGl_Vec4* )theEdgeColour->rgb);
477 aGlContext->SetTypeOfLine (anAspect->Type());
478 aGlContext->SetLineWidth (anAspect->Width());
479
7d3e64ef 480 if (!myVboIndices.IsNull())
bf75be98 481 {
7d3e64ef 482 myVboIndices->Bind (aGlContext);
483 GLubyte* anOffset = myVboIndices->GetDataOffset();
2166f0fa 484
7d3e64ef 485 // draw primitives by vertex count with the indices
486 if (!myBounds.IsNull())
2166f0fa 487 {
7d3e64ef 488 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
871fa103 489 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
2166f0fa 490 {
871fa103 491 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
7d3e64ef 492 glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
493 anOffset += aStride * aNbElemsInGroup;
7fd59977 494 }
495 }
7d3e64ef 496 // draw one (or sequential) primitive by the indices
2166f0fa
SK
497 else
498 {
7d3e64ef 499 glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
762aacae 500 }
7d3e64ef 501 myVboIndices->Unbind (aGlContext);
2166f0fa 502 }
7d3e64ef 503 else if (!myBounds.IsNull())
2166f0fa 504 {
7d3e64ef 505 GLint aFirstElem = 0;
506 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
2166f0fa 507 {
7d3e64ef 508 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
509 glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
510 aFirstElem += aNbElemsInGroup;
7fd59977 511 }
2166f0fa 512 }
7d3e64ef 513 else
514 {
515 glDrawArrays (myDrawMode, 0, myAttribs->NbElements);
516 }
517
518 // unbind buffers
519 myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS);
2166f0fa 520
8625ef7e 521 // restore line context
8625ef7e 522 theWorkspace->SetAspectLine (anAspectLineOld);
7fd59977 523}
524
2166f0fa 525// =======================================================================
7d3e64ef 526// function : drawMarkers
a577aaab 527// purpose :
528// =======================================================================
7d3e64ef 529void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
a577aaab 530{
531 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (Standard_True);
532 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
8625ef7e 533 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx);
534 if (!aSpriteNorm.IsNull()
535 && !aSpriteNorm->IsDisplayList())
a577aaab 536 {
537 // Textured markers will be drawn with the point sprites
8625ef7e 538 aCtx->SetPointSize (anAspectMarker->MarkerSize());
ca3c13d1 539 #if !defined(GL_ES_VERSION_2_0)
4e1523ef 540 if (aCtx->core11 != NULL)
541 {
542 aCtx->core11fwd->glEnable (GL_ALPHA_TEST);
543 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, 0.1f);
544 }
ca3c13d1 545 #endif
a577aaab 546
8625ef7e 547 aCtx->core11fwd->glEnable (GL_BLEND);
548 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
a577aaab 549
8625ef7e 550 aCtx->core11fwd->glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
a577aaab 551
8625ef7e 552 aCtx->core11fwd->glDisable (GL_BLEND);
ca3c13d1 553 #if !defined(GL_ES_VERSION_2_0)
4e1523ef 554 if (aCtx->core11 != NULL)
555 {
556 aCtx->core11fwd->glDisable (GL_ALPHA_TEST);
557 }
ca3c13d1 558 #endif
8625ef7e 559 aCtx->SetPointSize (1.0f);
a577aaab 560 return;
561 }
8625ef7e 562 else if (anAspectMarker->Type() == Aspect_TOM_POINT)
a577aaab 563 {
8625ef7e 564 aCtx->SetPointSize (anAspectMarker->MarkerSize());
565 aCtx->core11fwd->glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
566 aCtx->SetPointSize (1.0f);
a577aaab 567 }
ca3c13d1 568#if !defined(GL_ES_VERSION_2_0)
8625ef7e 569 // Textured markers will be drawn with the glBitmap
570 else if (anAspectMarker->Type() != Aspect_TOM_POINT
571 && !aSpriteNorm.IsNull())
a577aaab 572 {
871fa103 573 /**if (!isHilight && (myPArray->vcolours != NULL))
a577aaab 574 {
871fa103 575 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
a577aaab 576 {
871fa103 577 glColor4ubv (myPArray->vcolours[anIter].GetData());
578 glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
a577aaab 579 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
580 }
581 }
871fa103 582 else*/
a577aaab 583 {
871fa103 584 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
a577aaab 585 {
8625ef7e 586 aCtx->core11->glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
a577aaab 587 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
588 }
589 }
590 }
ca3c13d1 591#endif
a577aaab 592}
593
594// =======================================================================
2166f0fa
SK
595// function : OpenGl_PrimitiveArray
596// purpose :
597// =======================================================================
e1c659da 598OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver)
599
600: myDrawMode (DRAW_MODE_NONE),
601 myIsVboInit (Standard_False)
602{
603 if (theDriver != NULL)
604 {
605 myUID = theDriver->GetNextPrimitiveArrayUID();
606 }
607}
608
609// =======================================================================
610// function : OpenGl_PrimitiveArray
611// purpose :
612// =======================================================================
8d3f219f 613OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver,
614 const Graphic3d_TypeOfPrimitiveArray theType,
871fa103 615 const Handle(Graphic3d_IndexBuffer)& theIndices,
616 const Handle(Graphic3d_Buffer)& theAttribs,
617 const Handle(Graphic3d_BoundBuffer)& theBounds)
8d3f219f 618
871fa103 619: myIndices (theIndices),
620 myAttribs (theAttribs),
621 myBounds (theBounds),
622 myDrawMode (DRAW_MODE_NONE),
c827ea3a 623 myIsVboInit (Standard_False)
2166f0fa 624{
871fa103 625 if (!myIndices.IsNull()
626 && myIndices->NbElements < 1)
627 {
628 // dummy index buffer?
629 myIndices.Nullify();
630 }
871fa103 631
e99a2f7c 632 if (theDriver != NULL)
633 {
634 myUID = theDriver->GetNextPrimitiveArrayUID();
635 #if defined (GL_ES_VERSION_2_0)
636 const Handle(OpenGl_Context)& aCtx = theDriver->GetSharedContext();
637 if (!aCtx.IsNull())
638 {
639 processIndices (aCtx);
640 }
641 #endif
642 }
643
a79f67f8 644 setDrawMode (theType);
2166f0fa
SK
645}
646
647// =======================================================================
648// function : ~OpenGl_PrimitiveArray
649// purpose :
650// =======================================================================
5e27df78 651OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
2166f0fa 652{
5e27df78 653 //
654}
2166f0fa 655
5e27df78 656// =======================================================================
657// function : Release
658// purpose :
659// =======================================================================
10b9c7df 660void OpenGl_PrimitiveArray::Release (OpenGl_Context* theContext)
5e27df78 661{
c827ea3a 662 myIsVboInit = Standard_False;
871fa103 663 if (!myVboIndices.IsNull())
2166f0fa 664 {
10b9c7df 665 if (theContext)
5e27df78 666 {
871fa103 667 theContext->DelayedRelease (myVboIndices);
668 }
669 myVboIndices.Nullify();
670 }
671 if (!myVboAttribs.IsNull())
672 {
10b9c7df 673 if (theContext)
871fa103 674 {
675 theContext->DelayedRelease (myVboAttribs);
5e27df78 676 }
871fa103 677 myVboAttribs.Nullify();
2166f0fa
SK
678 }
679}
680
681// =======================================================================
682// function : Render
683// purpose :
684// =======================================================================
685void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
686{
871fa103 687 if (myDrawMode == DRAW_MODE_NONE)
bf75be98 688 {
2166f0fa 689 return;
bf75be98 690 }
2166f0fa 691
a577aaab 692 const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace (Standard_True);
693 const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True);
694 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (myDrawMode == GL_POINTS);
695
2166f0fa 696 // create VBOs on first render call
58655684 697 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
7d3e64ef 698 if (!myIsVboInit)
2166f0fa 699 {
7d3e64ef 700 // compatibility - keep data to draw markers using display lists
701 const Standard_Boolean toKeepData = myDrawMode == GL_POINTS
8625ef7e 702 && !anAspectMarker->SpriteRes (aCtx).IsNull()
703 && anAspectMarker->SpriteRes (aCtx)->IsDisplayList();
e99a2f7c 704 #if defined (GL_ES_VERSION_2_0)
705 processIndices (aCtx);
706 #endif
7d3e64ef 707 buildVBO (aCtx, toKeepData);
5e27df78 708 myIsVboInit = Standard_True;
2166f0fa
SK
709 }
710
fd4a6963 711 Tint aFrontLightingModel = anAspectFace->IntFront().color_mask;
712 const TEL_COLOUR* anInteriorColor = &anAspectFace->IntFront().matcol;
2166f0fa 713 const TEL_COLOUR* anEdgeColor = &anAspectFace->AspectEdge()->Color();
871fa103 714 const TEL_COLOUR* aLineColor = myDrawMode == GL_POINTS ? &anAspectMarker->Color() : &anAspectLine->Color();
2166f0fa
SK
715
716 // Use highlight colors
717 if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
bf75be98 718 {
2166f0fa
SK
719 anEdgeColor = anInteriorColor = aLineColor = theWorkspace->HighlightColor;
720 aFrontLightingModel = 0;
721 }
722
8625ef7e 723 const Standard_Boolean hasColorAttrib = !myVboAttribs.IsNull()
724 && myVboAttribs->HasColorAttribute();
725 const Standard_Boolean isLightOn = aFrontLightingModel != 0
726 && !myVboAttribs.IsNull()
727 && myVboAttribs->HasNormalAttribute();
ca3c13d1 728#if !defined(GL_ES_VERSION_2_0)
7d3e64ef 729 // manage FFP lighting
4e1523ef 730 if (aCtx->core11 != NULL)
7d3e64ef 731 {
4e1523ef 732 if (!isLightOn)
733 {
734 glDisable (GL_LIGHTING);
735 }
736 else
737 {
738 glEnable (GL_LIGHTING);
739 }
7d3e64ef 740 }
ca3c13d1 741#endif
8625ef7e 742 // Temporarily disable environment mapping
743 Handle(OpenGl_Texture) aTextureBack;
744 if (myDrawMode <= GL_LINE_STRIP)
745 {
746 aTextureBack = theWorkspace->DisableTexture();
747 }
7d3e64ef 748
749 if ((myDrawMode > GL_LINE_STRIP && anAspectFace->InteriorStyle() != Aspect_IS_EMPTY) ||
750 (myDrawMode <= GL_LINE_STRIP))
751 {
752 const bool toHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0;
753 const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->InteriorStyle() != Aspect_IS_HIDDENLINE
754 ? myBounds->Colors
755 : NULL;
8625ef7e 756 const Standard_Boolean hasVertColor = hasColorAttrib && !toHilight;
4e1523ef 757 if (aCtx->core20fwd != NULL)
8625ef7e 758 {
759 switch (myDrawMode)
760 {
761 case GL_POINTS:
762 {
763 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx);
764 if (!aSpriteNorm.IsNull()
765 && !aSpriteNorm->IsDisplayList())
766 {
767 const Handle(OpenGl_PointSprite)& aSprite = (toHilight && anAspectMarker->SpriteHighlightRes (aCtx)->IsValid())
768 ? anAspectMarker->SpriteHighlightRes (aCtx)
769 : aSpriteNorm;
770 theWorkspace->EnableTexture (aSprite);
771 aCtx->ShaderManager()->BindProgram (anAspectMarker, aSprite, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
772 }
773 else
774 {
775 aCtx->ShaderManager()->BindProgram (anAspectMarker, NULL, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
776 }
777 break;
778 }
779 case GL_LINES:
780 case GL_LINE_STRIP:
781 {
782 aCtx->ShaderManager()->BindProgram (anAspectLine, NULL, isLightOn, hasVertColor, anAspectLine->ShaderProgramRes (aCtx));
783 break;
784 }
785 default:
786 {
79f4f036 787 const Handle(OpenGl_Texture)& aTexture = theWorkspace->ActiveTexture();
6c6aadb1 788 const Standard_Boolean isLightOnFace = isLightOn
79f4f036 789 && (aTexture.IsNull()
790 || aTexture->GetParams()->IsModulate());
791 aCtx->ShaderManager()->BindProgram (anAspectFace, aTexture, isLightOnFace, hasVertColor, anAspectFace->ShaderProgramRes (aCtx));
8625ef7e 792 break;
793 }
794 }
795 }
796
79f4f036 797 if (!theWorkspace->ActiveTexture().IsNull()
798 && myDrawMode != GL_POINTS) // transformation is not supported within point sprites
799 {
800 aCtx->SetTextureMatrix (theWorkspace->ActiveTexture()->GetParams());
801 }
802
8625ef7e 803 aCtx->SetColor4fv (*(const OpenGl_Vec4* )(myDrawMode <= GL_LINE_STRIP ? aLineColor->rgb : anInteriorColor->rgb));
ac116c22 804 if (myDrawMode == GL_LINES
805 || myDrawMode == GL_LINE_STRIP)
806 {
807 aCtx->SetTypeOfLine (anAspectLine->Type());
808 aCtx->SetLineWidth (anAspectLine->Width());
809 }
7d3e64ef 810
8625ef7e 811 drawArray (theWorkspace, aFaceColors, hasColorAttrib);
7d3e64ef 812 }
813
8625ef7e 814 if (myDrawMode <= GL_LINE_STRIP)
815 {
816 theWorkspace->EnableTexture (aTextureBack);
817 }
818 else
7d3e64ef 819 {
820 if (anAspectFace->Edge()
821 || anAspectFace->InteriorStyle() == Aspect_IS_HIDDENLINE)
30f0ad28 822 {
7d3e64ef 823 drawEdges (anEdgeColor, theWorkspace);
b34efb62 824
b34efb62 825 // restore OpenGL polygon mode if needed
65360da3 826 #if !defined(GL_ES_VERSION_2_0)
b34efb62 827 if (anAspectFace->InteriorStyle() >= Aspect_IS_HATCH)
828 {
829 glPolygonMode (GL_FRONT_AND_BACK,
830 anAspectFace->InteriorStyle() == Aspect_IS_POINT ? GL_POINT : GL_FILL);
831 }
832 #endif
30f0ad28 833 }
834 }
835
7d3e64ef 836 aCtx->BindProgram (NULL);
2166f0fa 837}
a79f67f8 838
839// =======================================================================
840// function : setDrawMode
841// purpose :
842// =======================================================================
843void OpenGl_PrimitiveArray::setDrawMode (const Graphic3d_TypeOfPrimitiveArray theType)
844{
845 if (myAttribs.IsNull())
846 {
847 myDrawMode = DRAW_MODE_NONE;
848 return;
849 }
850
851 switch (theType)
852 {
853 case Graphic3d_TOPA_POINTS:
854 myDrawMode = GL_POINTS;
855 break;
856 case Graphic3d_TOPA_POLYLINES:
857 myDrawMode = GL_LINE_STRIP;
858 break;
859 case Graphic3d_TOPA_SEGMENTS:
860 myDrawMode = GL_LINES;
861 break;
862 case Graphic3d_TOPA_TRIANGLES:
863 myDrawMode = GL_TRIANGLES;
864 break;
865 case Graphic3d_TOPA_TRIANGLESTRIPS:
866 myDrawMode = GL_TRIANGLE_STRIP;
867 break;
868 case Graphic3d_TOPA_TRIANGLEFANS:
869 myDrawMode = GL_TRIANGLE_FAN;
870 break;
871 #if !defined(GL_ES_VERSION_2_0)
872 case Graphic3d_TOPA_POLYGONS:
873 myDrawMode = GL_POLYGON;
874 break;
875 case Graphic3d_TOPA_QUADRANGLES:
876 myDrawMode = GL_QUADS;
877 break;
878 case Graphic3d_TOPA_QUADRANGLESTRIPS:
879 myDrawMode = GL_QUAD_STRIP;
880 break;
881 #else
882 case Graphic3d_TOPA_POLYGONS:
883 case Graphic3d_TOPA_QUADRANGLES:
884 case Graphic3d_TOPA_QUADRANGLESTRIPS:
885 #endif
886 case Graphic3d_TOPA_UNDEFINED:
887 break;
888 }
889}
890
891// =======================================================================
e99a2f7c 892// function : processIndices
893// purpose :
894// =======================================================================
895Standard_Boolean OpenGl_PrimitiveArray::processIndices (const Handle(OpenGl_Context)& theContext) const
896{
897 if (myIndices.IsNull()
898 || theContext->hasUintIndex)
899 {
900 return Standard_True;
901 }
902
903 if (myIndices->NbElements > std::numeric_limits<GLushort>::max())
904 {
905 Handle(Graphic3d_Buffer) anAttribs = new Graphic3d_Buffer (new NCollection_AlignedAllocator (16));
906 if (!anAttribs->Init (myIndices->NbElements, myAttribs->AttributesArray(), myAttribs->NbAttributes))
907 {
908 return Standard_False; // failed to initialize attribute array
909 }
910
911 for (Standard_Integer anIdxIdx = 0; anIdxIdx < myIndices->NbElements; ++anIdxIdx)
912 {
913 const Standard_Integer anIndex = myIndices->Index (anIdxIdx);
914 memcpy (anAttribs->ChangeData() + myAttribs->Stride * anIdxIdx,
915 myAttribs->Data() + myAttribs->Stride * anIndex,
916 myAttribs->Stride);
917 }
918
919 myIndices.Nullify();
920 myAttribs = anAttribs;
921 }
922
923 return Standard_True;
924}
925
926// =======================================================================
a79f67f8 927// function : InitBuffers
928// purpose :
929// =======================================================================
930void OpenGl_PrimitiveArray::InitBuffers (const Handle(OpenGl_Context)& theContext,
931 const Graphic3d_TypeOfPrimitiveArray theType,
932 const Handle(Graphic3d_IndexBuffer)& theIndices,
933 const Handle(Graphic3d_Buffer)& theAttribs,
934 const Handle(Graphic3d_BoundBuffer)& theBounds)
935{
936 // Release old graphic resources
937 Release (theContext.operator->());
938
939 myIndices = theIndices;
940 myAttribs = theAttribs;
941 myBounds = theBounds;
e99a2f7c 942#if defined(GL_ES_VERSION_2_0)
943 processIndices (theContext);
944#endif
a79f67f8 945
946 setDrawMode (theType);
947}