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