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