1 // Created on: 2011-07-13
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2013 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <OpenGl_PrimitiveArray.hxx>
17
18 #include <OpenGl_Aspects.hxx>
19 #include <OpenGl_Context.hxx>
20 #include <OpenGl_GraphicDriver.hxx>
21 #include <OpenGl_IndexBuffer.hxx>
22 #include <OpenGl_PointSprite.hxx>
23 #include <OpenGl_Sampler.hxx>
24 #include <OpenGl_ShaderManager.hxx>
25 #include <OpenGl_ShaderProgram.hxx>
26 #include <OpenGl_Structure.hxx>
27 #include <OpenGl_VertexBufferCompat.hxx>
28 #include <OpenGl_View.hxx>
29 #include <OpenGl_Workspace.hxx>
30 #include <Graphic3d_TextureParams.hxx>
31
32 namespace
33 {
34 //! Convert data type to GL info
toGlDataType(const Graphic3d_TypeOfData theType,GLint & theNbComp)35 inline GLenum toGlDataType (const Graphic3d_TypeOfData theType,
36 GLint& theNbComp)
37 {
38 switch (theType)
39 {
40 case Graphic3d_TOD_USHORT:
41 theNbComp = 1;
42 return GL_UNSIGNED_SHORT;
43 case Graphic3d_TOD_UINT:
44 theNbComp = 1;
45 return GL_UNSIGNED_INT;
46 case Graphic3d_TOD_VEC2:
47 theNbComp = 2;
48 return GL_FLOAT;
49 case Graphic3d_TOD_VEC3:
50 theNbComp = 3;
51 return GL_FLOAT;
52 case Graphic3d_TOD_VEC4:
53 theNbComp = 4;
54 return GL_FLOAT;
55 case Graphic3d_TOD_VEC4UB:
56 theNbComp = 4;
57 return GL_UNSIGNED_BYTE;
58 case Graphic3d_TOD_FLOAT:
59 theNbComp = 1;
60 return GL_FLOAT;
61 }
62 theNbComp = 0;
63 return GL_NONE;
64 }
65
66 }
67
68 //! Auxiliary template for VBO with interleaved attributes.
69 template<class TheBaseClass, int NbAttributes>
70 class OpenGl_VertexBufferT : public TheBaseClass
71 {
72 public:
73
74 //! Create uninitialized VBO.
OpenGl_VertexBufferT(const Graphic3d_Buffer & theAttribs)75 OpenGl_VertexBufferT (const Graphic3d_Buffer& theAttribs)
76 : Stride (theAttribs.IsInterleaved() ? theAttribs.Stride : 0)
77 {
78 memcpy (Attribs, theAttribs.AttributesArray(), sizeof(Graphic3d_Attribute) * NbAttributes);
79 }
80
HasColorAttribute() const81 virtual bool HasColorAttribute() const
82 {
83 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
84 {
85 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
86 if (anAttrib.Id == Graphic3d_TOA_COLOR)
87 {
88 return true;
89 }
90 }
91 return false;
92 }
93
HasNormalAttribute() const94 virtual bool HasNormalAttribute() const
95 {
96 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
97 {
98 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
99 if (anAttrib.Id == Graphic3d_TOA_NORM)
100 {
101 return true;
102 }
103 }
104 return false;
105 }
106
BindPositionAttribute(const Handle (OpenGl_Context)& theGlCtx) const107 virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const
108 {
109 if (!TheBaseClass::IsValid())
110 {
111 return;
112 }
113
114 TheBaseClass::Bind (theGlCtx);
115 GLint aNbComp;
116 const GLubyte* anOffset = TheBaseClass::myOffset;
117 const Standard_Size aMuliplier = Stride != 0 ? 1 : TheBaseClass::myElemsNb;
118 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
119 {
120 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
121 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
122 if (anAttrib.Id == Graphic3d_TOA_POS
123 && aDataType != GL_NONE)
124 {
125 TheBaseClass::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
126 break;
127 }
128
129 anOffset += aMuliplier * Graphic3d_Attribute::Stride (anAttrib.DataType);
130 }
131 }
132
BindAllAttributes(const Handle (OpenGl_Context)& theGlCtx) const133 virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
134 {
135 if (!TheBaseClass::IsValid())
136 {
137 return;
138 }
139
140 TheBaseClass::Bind (theGlCtx);
141 GLint aNbComp;
142 const GLubyte* anOffset = TheBaseClass::myOffset;
143 const Standard_Size aMuliplier = Stride != 0 ? 1 : TheBaseClass::myElemsNb;
144 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
145 {
146 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
147 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
148 if (aDataType != GL_NONE)
149 {
150 TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
151 }
152 anOffset += aMuliplier * Graphic3d_Attribute::Stride (anAttrib.DataType);
153 }
154 }
155
UnbindAllAttributes(const Handle (OpenGl_Context)& theGlCtx) const156 virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
157 {
158 if (!TheBaseClass::IsValid())
159 {
160 return;
161 }
162 TheBaseClass::Unbind (theGlCtx);
163
164 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
165 {
166 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
167 TheBaseClass::unbindAttribute (theGlCtx, anAttrib.Id);
168 }
169 }
170
171 private:
172
173 Graphic3d_Attribute Attribs[NbAttributes];
174 Standard_Integer Stride;
175
176 };
177
178 // =======================================================================
179 // function : clearMemoryGL
180 // purpose :
181 // =======================================================================
clearMemoryGL(const Handle (OpenGl_Context)& theGlCtx) const182 void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
183 {
184 if (!myVboIndices.IsNull())
185 {
186 myVboIndices->Release (theGlCtx.operator->());
187 myVboIndices.Nullify();
188 }
189 if (!myVboAttribs.IsNull())
190 {
191 myVboAttribs->Release (theGlCtx.operator->());
192 myVboAttribs.Nullify();
193 }
194 }
195
196 // =======================================================================
197 // function : initNormalVbo
198 // purpose :
199 // =======================================================================
initNormalVbo(const Handle (OpenGl_Context)& theCtx) const200 Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Context)& theCtx) const
201 {
202 switch (myAttribs->NbAttributes)
203 {
204 case 1: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 1> (*myAttribs); break;
205 case 2: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 2> (*myAttribs); break;
206 case 3: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 3> (*myAttribs); break;
207 case 4: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 4> (*myAttribs); break;
208 case 5: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 5> (*myAttribs); break;
209 case 6: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 6> (*myAttribs); break;
210 case 7: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 7> (*myAttribs); break;
211 case 8: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 8> (*myAttribs); break;
212 case 9: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 9> (*myAttribs); break;
213 case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break;
214 }
215
216 const Standard_Boolean isAttribMutable = myAttribs->IsMutable();
217 const Standard_Boolean isAttribInterleaved = myAttribs->IsInterleaved();
218 if (myAttribs->NbElements != myAttribs->NbMaxElements()
219 && myIndices.IsNull()
220 && (!isAttribInterleaved || isAttribMutable))
221 {
222 throw Standard_ProgramError ("OpenGl_PrimitiveArray::buildVBO() - vertex attribute data with reserved size is not supported");
223 }
224
225 // specify data type as Byte and NbComponents as Stride, so that OpenGl_VertexBuffer::EstimatedDataSize() will return correct value
226 const Standard_Integer aNbVertexes = (isAttribMutable || !isAttribInterleaved) ? myAttribs->NbMaxElements() : myAttribs->NbElements;
227 if (!myVboAttribs->init (theCtx, myAttribs->Stride, aNbVertexes, myAttribs->Data(), GL_UNSIGNED_BYTE, myAttribs->Stride))
228 {
229 TCollection_ExtendedString aMsg = TCollection_ExtendedString("VBO creation for Primitive Array has failed for ") + aNbVertexes + " vertices. Out of memory?";
230 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
231
232 clearMemoryGL (theCtx);
233 return Standard_False;
234 }
235 else if (myIndices.IsNull())
236 {
237 if (isAttribMutable && isAttribInterleaved)
238 {
239 // for mutable interlaced array we can change dynamically number of vertexes (they will be just skipped at the end of buffer);
240 // this doesn't matter in case if we have indexed array
241 myVboAttribs->SetElemsNb (myAttribs->NbElements);
242 }
243 return Standard_True;
244 }
245
246 const Standard_Integer aNbIndexes = !myIndices->IsMutable() ? myIndices->NbElements : myIndices->NbMaxElements();
247 myVboIndices = new OpenGl_IndexBuffer();
248 bool isOk = false;
249 switch (myIndices->Stride)
250 {
251 case 2:
252 {
253 isOk = myVboIndices->Init (theCtx, 1, aNbIndexes, reinterpret_cast<const GLushort*> (myIndices->Data()));
254 myVboIndices->SetElemsNb (myIndices->NbElements);
255 myIndices->Validate();
256 break;
257 }
258 case 4:
259 {
260 isOk = myVboIndices->Init (theCtx, 1, aNbIndexes, reinterpret_cast<const GLuint*> (myIndices->Data()));
261 myVboIndices->SetElemsNb (myIndices->NbElements);
262 myIndices->Validate();
263 break;
264 }
265 default:
266 {
267 clearMemoryGL (theCtx);
268 return Standard_False;
269 }
270 }
271 if (!isOk)
272 {
273 TCollection_ExtendedString aMsg = TCollection_ExtendedString("VBO creation for Primitive Array has failed for ") + aNbIndexes + " indices. Out of memory?";
274 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
275 clearMemoryGL (theCtx);
276 return Standard_False;
277 }
278 return Standard_True;
279 }
280
281 // =======================================================================
282 // function : buildVBO
283 // purpose :
284 // =======================================================================
buildVBO(const Handle (OpenGl_Context)& theCtx,const Standard_Boolean theToKeepData) const285 Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& theCtx,
286 const Standard_Boolean theToKeepData) const
287 {
288 bool isNormalMode = theCtx->ToUseVbo();
289 clearMemoryGL (theCtx);
290 if (myAttribs.IsNull()
291 || myAttribs->IsEmpty()
292 || myAttribs->NbElements < 1
293 || myAttribs->NbAttributes < 1
294 || myAttribs->NbAttributes > 10)
295 {
296 // vertices should be always defined - others are optional
297 return Standard_False;
298 }
299
300 if (isNormalMode
301 && initNormalVbo (theCtx))
302 {
303 if (!theCtx->caps->keepArrayData
304 && !theToKeepData
305 && !myAttribs->IsMutable())
306 {
307 myIndices.Nullify();
308 myAttribs.Nullify();
309 }
310 else
311 {
312 myAttribs->Validate();
313 }
314 return Standard_True;
315 }
316
317 Handle(OpenGl_VertexBufferCompat) aVboAttribs;
318 switch (myAttribs->NbAttributes)
319 {
320 case 1: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 1> (*myAttribs); break;
321 case 2: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 2> (*myAttribs); break;
322 case 3: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 3> (*myAttribs); break;
323 case 4: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 4> (*myAttribs); break;
324 case 5: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 5> (*myAttribs); break;
325 case 6: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 6> (*myAttribs); break;
326 case 7: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 7> (*myAttribs); break;
327 case 8: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 8> (*myAttribs); break;
328 case 9: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 9> (*myAttribs); break;
329 case 10: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 10>(*myAttribs); break;
330 }
331 aVboAttribs->initLink (myAttribs, 0, myAttribs->NbElements, GL_NONE);
332 if (!myIndices.IsNull())
333 {
334 Handle(OpenGl_IndexBufferCompat) aVboIndices = new OpenGl_IndexBufferCompat();
335 switch (myIndices->Stride)
336 {
337 case 2:
338 {
339 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_SHORT);
340 break;
341 }
342 case 4:
343 {
344 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_INT);
345 break;
346 }
347 default:
348 {
349 return Standard_False;
350 }
351 }
352 myVboIndices = aVboIndices;
353 }
354 myVboAttribs = aVboAttribs;
355 if (!theCtx->caps->keepArrayData
356 && !theToKeepData)
357 {
358 // does not make sense for compatibility mode
359 //myIndices.Nullify();
360 //myAttribs.Nullify();
361 }
362
363 return Standard_True;
364 }
365
366 // =======================================================================
367 // function : updateVBO
368 // purpose :
369 // =======================================================================
updateVBO(const Handle (OpenGl_Context)& theCtx) const370 void OpenGl_PrimitiveArray::updateVBO (const Handle(OpenGl_Context)& theCtx) const
371 {
372 if (!myAttribs.IsNull())
373 {
374 Graphic3d_BufferRange aRange = myAttribs->InvalidatedRange();
375 if (!aRange.IsEmpty()
376 && myVboAttribs->IsValid()
377 && !myVboAttribs->IsVirtual())
378 {
379 myVboAttribs->Bind (theCtx);
380 theCtx->core15fwd->glBufferSubData (myVboAttribs->GetTarget(),
381 aRange.Start,
382 aRange.Length,
383 myAttribs->Data() + aRange.Start);
384 myVboAttribs->Unbind (theCtx);
385 if (myAttribs->IsInterleaved())
386 {
387 myVboAttribs->SetElemsNb (myAttribs->NbElements);
388 }
389 }
390 myAttribs->Validate();
391 }
392 if (!myIndices.IsNull())
393 {
394 Graphic3d_BufferRange aRange = myIndices->InvalidatedRange();
395 if (!aRange.IsEmpty()
396 && myVboIndices->IsValid()
397 && !myVboIndices->IsVirtual())
398 {
399 myVboIndices->Bind (theCtx);
400 theCtx->core15fwd->glBufferSubData (myVboIndices->GetTarget(),
401 aRange.Start,
402 aRange.Length,
403 myIndices->Data() + aRange.Start);
404 myVboIndices->Unbind (theCtx);
405 myVboIndices->SetElemsNb (myIndices->NbElements);
406 }
407 myIndices->Validate();
408 }
409 }
410
411 // =======================================================================
412 // function : drawArray
413 // purpose :
414 // =======================================================================
drawArray(const Handle (OpenGl_Workspace)& theWorkspace,const Graphic3d_Vec4 * theFaceColors,const Standard_Boolean theHasVertColor) const415 void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorkspace,
416 const Graphic3d_Vec4* theFaceColors,
417 const Standard_Boolean theHasVertColor) const
418 {
419 if (myVboAttribs.IsNull())
420 {
421 #if !defined(GL_ES_VERSION_2_0)
422 if (myDrawMode == GL_POINTS)
423 {
424 // extreme compatibility mode - without sprites but with markers
425 drawMarkers (theWorkspace);
426 }
427 #endif
428 return;
429 }
430
431 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
432 const bool toHilight = theWorkspace->ToHighlight();
433 const GLenum aDrawMode = !aGlContext->ActiveProgram().IsNull()
434 && aGlContext->ActiveProgram()->HasTessellationStage()
435 ? GL_PATCHES
436 : myDrawMode;
437 myVboAttribs->BindAllAttributes (aGlContext);
438 if (theHasVertColor && toHilight)
439 {
440 // disable per-vertex color
441 OpenGl_VertexBuffer::unbindAttribute (aGlContext, Graphic3d_TOA_COLOR);
442 }
443 if (!myVboIndices.IsNull())
444 {
445 myVboIndices->Bind (aGlContext);
446 GLubyte* anOffset = myVboIndices->GetDataOffset();
447 if (!myBounds.IsNull())
448 {
449 // draw primitives by vertex count with the indices
450 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
451 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
452 {
453 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
454 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
455 glDrawElements (aDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
456 anOffset += aStride * aNbElemsInGroup;
457 }
458 }
459 else
460 {
461 // draw one (or sequential) primitive by the indices
462 glDrawElements (aDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
463 }
464 myVboIndices->Unbind (aGlContext);
465 }
466 else if (!myBounds.IsNull())
467 {
468 GLint aFirstElem = 0;
469 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
470 {
471 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
472 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
473 glDrawArrays (aDrawMode, aFirstElem, aNbElemsInGroup);
474 aFirstElem += aNbElemsInGroup;
475 }
476 }
477 else
478 {
479 if (myDrawMode == GL_POINTS)
480 {
481 drawMarkers (theWorkspace);
482 }
483 else
484 {
485 glDrawArrays (aDrawMode, 0, myVboAttribs->GetElemsNb());
486 }
487 }
488
489 // bind with 0
490 myVboAttribs->UnbindAllAttributes (aGlContext);
491 }
492
493 // =======================================================================
494 // function : drawEdges
495 // purpose :
496 // =======================================================================
drawEdges(const Handle (OpenGl_Workspace)& theWorkspace) const497 void OpenGl_PrimitiveArray::drawEdges (const Handle(OpenGl_Workspace)& theWorkspace) const
498 {
499 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
500 if (myVboAttribs.IsNull())
501 {
502 return;
503 }
504
505 const OpenGl_Aspects* anAspect = theWorkspace->Aspects();
506 #if !defined(GL_ES_VERSION_2_0)
507 const Standard_Integer aPolyModeOld = aGlContext->SetPolygonMode (GL_LINE);
508 #endif
509
510 if (aGlContext->core20fwd != NULL)
511 {
512 aGlContext->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), anAspect->Aspect()->EdgeLineType(),
513 Graphic3d_TypeOfShadingModel_Unlit, Graphic3d_AlphaMode_Opaque, Standard_False,
514 anAspect->ShaderProgramRes (aGlContext));
515 }
516 aGlContext->SetSampleAlphaToCoverage (aGlContext->ShaderManager()->MaterialState().HasAlphaCutoff());
517 const GLenum aDrawMode = !aGlContext->ActiveProgram().IsNull()
518 && aGlContext->ActiveProgram()->HasTessellationStage()
519 ? GL_PATCHES
520 : myDrawMode;
521 #if !defined(GL_ES_VERSION_2_0)
522 if (aGlContext->ActiveProgram().IsNull()
523 && aGlContext->core11ffp != NULL)
524 {
525 aGlContext->core11fwd->glDisable (GL_LIGHTING);
526 }
527 #endif
528
529 /// OCC22236 NOTE: draw edges for all situations:
530 /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indices array
531 /// 2) draw elements from vertex array, when bounds defines count of primitive's vertices.
532 /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
533 myVboAttribs->BindPositionAttribute (aGlContext);
534
535 aGlContext->SetColor4fv (theWorkspace->EdgeColor().a() >= 0.1f
536 ? theWorkspace->EdgeColor()
537 : theWorkspace->View()->BackgroundColor());
538 aGlContext->SetLineStipple((float )anAspect->Aspect()->LineStippleFactor(), anAspect->Aspect()->LinePattern());
539 aGlContext->SetLineWidth (anAspect->Aspect()->EdgeWidth());
540
541 if (!myVboIndices.IsNull())
542 {
543 myVboIndices->Bind (aGlContext);
544 GLubyte* anOffset = myVboIndices->GetDataOffset();
545
546 // draw primitives by vertex count with the indices
547 if (!myBounds.IsNull())
548 {
549 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
550 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
551 {
552 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
553 aGlContext->core11fwd->glDrawElements (aDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
554 anOffset += aStride * aNbElemsInGroup;
555 }
556 }
557 // draw one (or sequential) primitive by the indices
558 else
559 {
560 aGlContext->core11fwd->glDrawElements (aDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
561 }
562 myVboIndices->Unbind (aGlContext);
563 }
564 else if (!myBounds.IsNull())
565 {
566 GLint aFirstElem = 0;
567 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
568 {
569 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
570 aGlContext->core11fwd->glDrawArrays (aDrawMode, aFirstElem, aNbElemsInGroup);
571 aFirstElem += aNbElemsInGroup;
572 }
573 }
574 else
575 {
576 aGlContext->core11fwd->glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
577 }
578
579 // unbind buffers
580 myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS);
581
582 // restore line context
583 #if !defined(GL_ES_VERSION_2_0)
584 aGlContext->SetPolygonMode (aPolyModeOld);
585 #endif
586 }
587
588 // =======================================================================
589 // function : drawMarkers
590 // purpose :
591 // =======================================================================
drawMarkers(const Handle (OpenGl_Workspace)& theWorkspace) const592 void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
593 {
594 const OpenGl_Aspects* anAspectMarker = theWorkspace->Aspects();
595 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
596 const GLenum aDrawMode = !aCtx->ActiveProgram().IsNull()
597 && aCtx->ActiveProgram()->HasTessellationStage()
598 ? GL_PATCHES
599 : myDrawMode;
600 if (anAspectMarker->Aspect()->MarkerType() == Aspect_TOM_POINT)
601 {
602 aCtx->SetPointSize (anAspectMarker->MarkerSize());
603 aCtx->core11fwd->glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
604 aCtx->SetPointSize (1.0f);
605 return;
606 }
607
608 #if !defined(GL_ES_VERSION_2_0)
609 if (aCtx->core11ffp != NULL)
610 {
611 aCtx->core11fwd->glEnable (GL_ALPHA_TEST);
612 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, 0.1f);
613 }
614 #endif
615 aCtx->core11fwd->glEnable (GL_BLEND);
616 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
617
618 if (anAspectMarker->HasPointSprite (aCtx))
619 {
620 // Textured markers will be drawn with the point sprites
621 aCtx->SetPointSize (anAspectMarker->MarkerSize());
622 aCtx->SetPointSpriteOrigin();
623
624 aCtx->core11fwd->glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
625
626 aCtx->SetPointSize (1.0f);
627 }
628 #if !defined(GL_ES_VERSION_2_0)
629 // Textured markers will be drawn with the glBitmap
630 else if (const Handle(OpenGl_PointSprite)& aSprite = anAspectMarker->SpriteRes (aCtx, theWorkspace->ToHighlight()))
631 {
632 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
633 {
634 aCtx->core11ffp->glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
635 aSprite->DrawBitmap (theWorkspace->GetGlContext());
636 }
637 }
638 #endif
639
640 aCtx->core11fwd->glDisable (GL_BLEND);
641 #if !defined(GL_ES_VERSION_2_0)
642 if (aCtx->core11ffp != NULL)
643 {
644 if (aCtx->ShaderManager()->MaterialState().AlphaCutoff() >= ShortRealLast())
645 {
646 aCtx->core11fwd->glDisable (GL_ALPHA_TEST);
647 }
648 else
649 {
650 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, aCtx->ShaderManager()->MaterialState().AlphaCutoff());
651 }
652 }
653 #endif
654 }
655
656 // =======================================================================
657 // function : OpenGl_PrimitiveArray
658 // purpose :
659 // =======================================================================
OpenGl_PrimitiveArray(const OpenGl_GraphicDriver * theDriver)660 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver)
661
662 : myDrawMode (DRAW_MODE_NONE),
663 myIsFillType(Standard_False),
664 myIsVboInit (Standard_False)
665 {
666 if (theDriver != NULL)
667 {
668 myUID = theDriver->GetNextPrimitiveArrayUID();
669 }
670 }
671
672 // =======================================================================
673 // function : OpenGl_PrimitiveArray
674 // purpose :
675 // =======================================================================
OpenGl_PrimitiveArray(const OpenGl_GraphicDriver * theDriver,const Graphic3d_TypeOfPrimitiveArray theType,const Handle (Graphic3d_IndexBuffer)& theIndices,const Handle (Graphic3d_Buffer)& theAttribs,const Handle (Graphic3d_BoundBuffer)& theBounds)676 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver,
677 const Graphic3d_TypeOfPrimitiveArray theType,
678 const Handle(Graphic3d_IndexBuffer)& theIndices,
679 const Handle(Graphic3d_Buffer)& theAttribs,
680 const Handle(Graphic3d_BoundBuffer)& theBounds)
681
682 : myIndices (theIndices),
683 myAttribs (theAttribs),
684 myBounds (theBounds),
685 myDrawMode (DRAW_MODE_NONE),
686 myIsFillType(Standard_False),
687 myIsVboInit (Standard_False)
688 {
689 if (!myIndices.IsNull()
690 && myIndices->NbElements < 1)
691 {
692 // dummy index buffer?
693 myIndices.Nullify();
694 }
695
696 if (theDriver != NULL)
697 {
698 myUID = theDriver->GetNextPrimitiveArrayUID();
699 #if defined (GL_ES_VERSION_2_0)
700 const Handle(OpenGl_Context)& aCtx = theDriver->GetSharedContext();
701 if (!aCtx.IsNull())
702 {
703 processIndices (aCtx);
704 }
705 #endif
706 }
707
708 setDrawMode (theType);
709 }
710
711 // =======================================================================
712 // function : ~OpenGl_PrimitiveArray
713 // purpose :
714 // =======================================================================
~OpenGl_PrimitiveArray()715 OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
716 {
717 //
718 }
719
720 // =======================================================================
721 // function : Release
722 // purpose :
723 // =======================================================================
Release(OpenGl_Context * theContext)724 void OpenGl_PrimitiveArray::Release (OpenGl_Context* theContext)
725 {
726 myIsVboInit = Standard_False;
727 if (!myVboIndices.IsNull())
728 {
729 if (theContext)
730 {
731 theContext->DelayedRelease (myVboIndices);
732 }
733 myVboIndices.Nullify();
734 }
735 if (!myVboAttribs.IsNull())
736 {
737 if (theContext)
738 {
739 theContext->DelayedRelease (myVboAttribs);
740 }
741 myVboAttribs.Nullify();
742 }
743 }
744
745 // =======================================================================
746 // function : EstimatedDataSize
747 // purpose :
748 // =======================================================================
EstimatedDataSize() const749 Standard_Size OpenGl_PrimitiveArray::EstimatedDataSize() const
750 {
751 Standard_Size aSize = 0;
752 if (!myVboAttribs.IsNull())
753 {
754 aSize += myVboAttribs->EstimatedDataSize();
755 }
756 if (!myVboIndices.IsNull())
757 {
758 aSize += myVboIndices->EstimatedDataSize();
759 }
760 return aSize;
761 }
762
763 // =======================================================================
764 // function : UpdateDrawStats
765 // purpose :
766 // =======================================================================
UpdateDrawStats(Graphic3d_FrameStatsDataTmp & theStats,bool theIsDetailed) const767 void OpenGl_PrimitiveArray::UpdateDrawStats (Graphic3d_FrameStatsDataTmp& theStats,
768 bool theIsDetailed) const
769 {
770 ++theStats[Graphic3d_FrameStatsCounter_NbElemsNotCulled];
771 if (myIsFillType)
772 {
773 ++theStats[Graphic3d_FrameStatsCounter_NbElemsFillNotCulled];
774 }
775 else if (myDrawMode == GL_POINTS)
776 {
777 ++theStats[Graphic3d_FrameStatsCounter_NbElemsPointNotCulled];
778 }
779 else
780 {
781 ++theStats[Graphic3d_FrameStatsCounter_NbElemsLineNotCulled];
782 }
783
784 if (!theIsDetailed
785 || myVboAttribs.IsNull()
786 || !myVboAttribs->IsValid())
787 {
788 return;
789 }
790
791 const Standard_Integer aNbIndices = !myVboIndices.IsNull() ? myVboIndices->GetElemsNb() : myVboAttribs->GetElemsNb();
792 const Standard_Integer aNbBounds = !myBounds.IsNull() ? myBounds->NbBounds : 1;
793 switch (myDrawMode)
794 {
795 case GL_POINTS:
796 {
797 theStats[Graphic3d_FrameStatsCounter_NbPointsNotCulled] += aNbIndices;
798 break;
799 }
800 case GL_LINES:
801 {
802 theStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled] += aNbIndices / 2;
803 break;
804 }
805 case GL_LINE_STRIP:
806 {
807 theStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled] += aNbIndices - aNbBounds;
808 break;
809 }
810 case GL_LINES_ADJACENCY:
811 {
812 theStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled] += aNbIndices / 4;
813 break;
814 }
815 case GL_LINE_STRIP_ADJACENCY:
816 {
817 theStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled] += aNbIndices - 4 * aNbBounds;
818 break;
819 }
820 case GL_TRIANGLES:
821 {
822 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices / 3;
823 break;
824 }
825 case GL_TRIANGLE_STRIP:
826 case GL_TRIANGLE_FAN:
827 {
828 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices - 2 * aNbBounds;
829 break;
830 }
831 case GL_TRIANGLES_ADJACENCY:
832 {
833 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices / 6;
834 break;
835 }
836 case GL_TRIANGLE_STRIP_ADJACENCY:
837 {
838 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices - 4 * aNbBounds;
839 break;
840 }
841 #if !defined(GL_ES_VERSION_2_0)
842 case GL_QUADS:
843 {
844 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices / 2;
845 break;
846 }
847 case GL_QUAD_STRIP:
848 {
849 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += (aNbIndices / 2 - aNbBounds) * 2;
850 break;
851 }
852 #endif
853 }
854 }
855
856 // =======================================================================
857 // function : Render
858 // purpose :
859 // =======================================================================
Render(const Handle (OpenGl_Workspace)& theWorkspace) const860 void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
861 {
862 if (myDrawMode == DRAW_MODE_NONE)
863 {
864 return;
865 }
866
867 const OpenGl_Aspects* anAspectFace = theWorkspace->Aspects();
868 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
869
870 bool toDrawArray = true, toSetLinePolygMode = false;
871 int toDrawInteriorEdges = 0; // 0 - no edges, 1 - glsl edges, 2 - polygonMode
872 if (myIsFillType)
873 {
874 toDrawArray = anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_EMPTY;
875 if (anAspectFace->Aspect()->ToDrawEdges())
876 {
877 toDrawInteriorEdges = 1;
878 toDrawArray = true;
879 #if !defined(GL_ES_VERSION_2_0)
880 if (anAspectFace->Aspect()->EdgeLineType() != Aspect_TOL_SOLID
881 || aCtx->hasGeometryStage == OpenGl_FeatureNotAvailable
882 || aCtx->caps->usePolygonMode)
883 {
884 toDrawInteriorEdges = 2;
885 if (anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_EMPTY)
886 {
887 if (anAspectFace->Aspect()->EdgeLineType() != Aspect_TOL_SOLID)
888 {
889 toDrawArray = false;
890 }
891 else
892 {
893 toSetLinePolygMode = true;
894 }
895 }
896 }
897 #endif
898 }
899 }
900 else
901 {
902 if (myDrawMode == GL_POINTS)
903 {
904 if (anAspectFace->Aspect()->MarkerType() == Aspect_TOM_EMPTY)
905 {
906 return;
907 }
908 }
909 else
910 {
911 if (anAspectFace->Aspect()->LineType() == Aspect_TOL_EMPTY)
912 {
913 return;
914 }
915 }
916 }
917
918 // create VBOs on first render call
919 if (!myIsVboInit)
920 {
921 // compatibility - keep data to draw markers using display lists
922 Standard_Boolean toKeepData = myDrawMode == GL_POINTS
923 && anAspectFace->IsDisplayListSprite (aCtx);
924 #if defined (GL_ES_VERSION_2_0)
925 processIndices (aCtx);
926 #endif
927 buildVBO (aCtx, toKeepData);
928 myIsVboInit = Standard_True;
929 }
930 else if ((!myAttribs.IsNull()
931 && myAttribs->IsMutable())
932 || (!myIndices.IsNull()
933 && myIndices->IsMutable()))
934 {
935 updateVBO (aCtx);
936 }
937
938 Graphic3d_TypeOfShadingModel aShadingModel = Graphic3d_TypeOfShadingModel_Unlit;
939 anAspectFace = theWorkspace->ApplyAspects (false); // do not bind textures before binding the program
940 const Handle(OpenGl_TextureSet)& aTextureSet = theWorkspace->TextureSet();
941 const bool toEnableEnvMap = !aTextureSet.IsNull()
942 && aTextureSet == theWorkspace->EnvironmentTexture();
943 if (toDrawArray)
944 {
945 const bool hasColorAttrib = !myVboAttribs.IsNull()
946 && myVboAttribs->HasColorAttribute();
947 const bool toHilight = theWorkspace->ToHighlight();
948 const bool hasVertColor = hasColorAttrib && !toHilight;
949 const bool hasVertNorm = !myVboAttribs.IsNull() && myVboAttribs->HasNormalAttribute();
950 switch (myDrawMode)
951 {
952 case GL_POINTS:
953 {
954 aShadingModel = aCtx->ShaderManager()->ChooseMarkerShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
955 aCtx->ShaderManager()->BindMarkerProgram (aTextureSet,
956 aShadingModel, Graphic3d_AlphaMode_Opaque,
957 hasVertColor, anAspectFace->ShaderProgramRes (aCtx));
958 break;
959 }
960 case GL_LINES:
961 case GL_LINE_STRIP:
962 {
963 aShadingModel = aCtx->ShaderManager()->ChooseLineShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
964 aCtx->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(),
965 anAspectFace->Aspect()->LineType(),
966 aShadingModel,
967 Graphic3d_AlphaMode_Opaque,
968 hasVertColor,
969 anAspectFace->ShaderProgramRes (aCtx));
970 break;
971 }
972 default:
973 {
974 aShadingModel = aCtx->ShaderManager()->ChooseFaceShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
975 aCtx->ShaderManager()->BindFaceProgram (aTextureSet,
976 aShadingModel,
977 aCtx->ShaderManager()->MaterialState().HasAlphaCutoff() ? Graphic3d_AlphaMode_Mask : Graphic3d_AlphaMode_Opaque,
978 toDrawInteriorEdges == 1 ? anAspectFace->Aspect()->InteriorStyle() : Aspect_IS_SOLID,
979 hasVertColor,
980 toEnableEnvMap,
981 toDrawInteriorEdges == 1,
982 anAspectFace->ShaderProgramRes (aCtx));
983 if (toDrawInteriorEdges == 1)
984 {
985 aCtx->ShaderManager()->PushInteriorState (aCtx->ActiveProgram(), anAspectFace->Aspect());
986 }
987 #if !defined (GL_ES_VERSION_2_0)
988 else if (toSetLinePolygMode)
989 {
990 aCtx->SetPolygonMode (GL_LINE);
991 }
992 #else
993 (void )toSetLinePolygMode;
994 #endif
995 break;
996 }
997 }
998
999 // bind textures after GLSL program to set mock textures to slots used by program
1000 aCtx->BindTextures (aTextureSet, aCtx->ActiveProgram());
1001 if (!aTextureSet.IsNull()
1002 && !aTextureSet->IsEmpty()
1003 && myDrawMode != GL_POINTS) // transformation is not supported within point sprites
1004 {
1005 if (const Handle(OpenGl_Texture)& aFirstTexture = aTextureSet->First())
1006 {
1007 aCtx->SetTextureMatrix (aFirstTexture->Sampler()->Parameters(), aFirstTexture->IsTopDown());
1008 }
1009 }
1010 aCtx->SetSampleAlphaToCoverage (aCtx->ShaderManager()->MaterialState().HasAlphaCutoff());
1011
1012 const bool isForcedBlend = anAspectFace->Aspect()->AlphaMode() == Graphic3d_AlphaMode_MaskBlend;
1013 if (isForcedBlend)
1014 {
1015 aCtx->core11fwd->glEnable (GL_BLEND);
1016 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1017 }
1018
1019 const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_HIDDENLINE
1020 ? myBounds->Colors
1021 : NULL;
1022 const OpenGl_Vec4& anInteriorColor = theWorkspace->InteriorColor();
1023 aCtx->SetColor4fv (anInteriorColor);
1024 if (!myIsFillType)
1025 {
1026 if (myDrawMode == GL_LINES
1027 || myDrawMode == GL_LINE_STRIP)
1028 {
1029 aCtx->SetLineStipple((float )anAspectFace->Aspect()->LineStippleFactor(), anAspectFace->Aspect()->LinePattern());
1030 aCtx->SetLineWidth (anAspectFace->Aspect()->LineWidth());
1031 }
1032
1033 drawArray (theWorkspace, aFaceColors, hasColorAttrib);
1034 if (isForcedBlend)
1035 {
1036 aCtx->core11fwd->glDisable (GL_BLEND);
1037 }
1038 return;
1039 }
1040
1041 drawArray (theWorkspace, aFaceColors, hasColorAttrib);
1042
1043 // draw outline - only closed triangulation with defined vertex normals can be drawn in this way
1044 if (anAspectFace->Aspect()->ToDrawSilhouette()
1045 && aCtx->ToCullBackFaces()
1046 && aCtx->ShaderManager()->BindOutlineProgram())
1047 {
1048 const Graphic3d_Vec2i aViewSize (aCtx->Viewport()[2], aCtx->Viewport()[3]);
1049 const Standard_Integer aMin = aViewSize.minComp();
1050 const GLfloat anEdgeWidth = (GLfloat )anAspectFace->Aspect()->EdgeWidth() * aCtx->LineWidthScale() / (GLfloat )aMin;
1051 const GLfloat anOrthoScale = aCtx->Camera()->IsOrthographic() ? (GLfloat )aCtx->Camera()->Scale() : -1.0f;
1052
1053 const Handle(OpenGl_ShaderProgram)& anOutlineProgram = aCtx->ActiveProgram();
1054 anOutlineProgram->SetUniform (aCtx, anOutlineProgram->GetStateLocation (OpenGl_OCCT_SILHOUETTE_THICKNESS), anEdgeWidth);
1055 anOutlineProgram->SetUniform (aCtx, anOutlineProgram->GetStateLocation (OpenGl_OCCT_ORTHO_SCALE), anOrthoScale);
1056 aCtx->SetColor4fv (anAspectFace->Aspect()->EdgeColorRGBA());
1057
1058 aCtx->core11fwd->glCullFace (GL_FRONT);
1059 drawArray (theWorkspace, NULL, false);
1060
1061 aCtx->core11fwd->glCullFace (GL_BACK);
1062 }
1063
1064 if (isForcedBlend)
1065 {
1066 aCtx->core11fwd->glDisable (GL_BLEND);
1067 }
1068 }
1069
1070 #if !defined(GL_ES_VERSION_2_0)
1071 // draw triangulation edges using Polygon Mode
1072 if (toDrawInteriorEdges == 2)
1073 {
1074 if (anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_HOLLOW
1075 && anAspectFace->Aspect()->EdgeLineType() == Aspect_TOL_SOLID)
1076 {
1077 aCtx->SetPolygonMode (GL_FILL);
1078 }
1079 else
1080 {
1081 drawEdges (theWorkspace);
1082 }
1083 }
1084 #endif
1085 }
1086
1087 // =======================================================================
1088 // function : setDrawMode
1089 // purpose :
1090 // =======================================================================
setDrawMode(const Graphic3d_TypeOfPrimitiveArray theType)1091 void OpenGl_PrimitiveArray::setDrawMode (const Graphic3d_TypeOfPrimitiveArray theType)
1092 {
1093 if (myAttribs.IsNull())
1094 {
1095 myDrawMode = DRAW_MODE_NONE;
1096 myIsFillType = false;
1097 return;
1098 }
1099
1100 switch (theType)
1101 {
1102 case Graphic3d_TOPA_POINTS:
1103 myDrawMode = GL_POINTS;
1104 myIsFillType = false;
1105 break;
1106 case Graphic3d_TOPA_SEGMENTS:
1107 myDrawMode = GL_LINES;
1108 myIsFillType = false;
1109 break;
1110 case Graphic3d_TOPA_POLYLINES:
1111 myDrawMode = GL_LINE_STRIP;
1112 myIsFillType = false;
1113 break;
1114 case Graphic3d_TOPA_TRIANGLES:
1115 myDrawMode = GL_TRIANGLES;
1116 myIsFillType = true;
1117 break;
1118 case Graphic3d_TOPA_TRIANGLESTRIPS:
1119 myDrawMode = GL_TRIANGLE_STRIP;
1120 myIsFillType = true;
1121 break;
1122 case Graphic3d_TOPA_TRIANGLEFANS:
1123 myDrawMode = GL_TRIANGLE_FAN;
1124 myIsFillType = true;
1125 break;
1126 //
1127 case Graphic3d_TOPA_LINES_ADJACENCY:
1128 myDrawMode = GL_LINES_ADJACENCY;
1129 myIsFillType = false;
1130 break;
1131 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
1132 myDrawMode = GL_LINE_STRIP_ADJACENCY;
1133 myIsFillType = false;
1134 break;
1135 case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
1136 myDrawMode = GL_TRIANGLES_ADJACENCY;
1137 myIsFillType = true;
1138 break;
1139 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
1140 myDrawMode = GL_TRIANGLE_STRIP_ADJACENCY;
1141 myIsFillType = true;
1142 break;
1143 //
1144 #if !defined(GL_ES_VERSION_2_0)
1145 case Graphic3d_TOPA_QUADRANGLES:
1146 myDrawMode = GL_QUADS;
1147 myIsFillType = true;
1148 break;
1149 case Graphic3d_TOPA_QUADRANGLESTRIPS:
1150 myDrawMode = GL_QUAD_STRIP;
1151 myIsFillType = true;
1152 break;
1153 case Graphic3d_TOPA_POLYGONS:
1154 myDrawMode = GL_POLYGON;
1155 myIsFillType = true;
1156 break;
1157 #else
1158 case Graphic3d_TOPA_QUADRANGLES:
1159 case Graphic3d_TOPA_QUADRANGLESTRIPS:
1160 case Graphic3d_TOPA_POLYGONS:
1161 #endif
1162 case Graphic3d_TOPA_UNDEFINED:
1163 myDrawMode = DRAW_MODE_NONE;
1164 myIsFillType = false;
1165 break;
1166 }
1167 }
1168
1169 // =======================================================================
1170 // function : processIndices
1171 // purpose :
1172 // =======================================================================
processIndices(const Handle (OpenGl_Context)& theContext) const1173 Standard_Boolean OpenGl_PrimitiveArray::processIndices (const Handle(OpenGl_Context)& theContext) const
1174 {
1175 if (myIndices.IsNull()
1176 || myAttribs.IsNull()
1177 || theContext->hasUintIndex)
1178 {
1179 return Standard_True;
1180 }
1181
1182 if (myAttribs->NbElements > std::numeric_limits<GLushort>::max())
1183 {
1184 Handle(Graphic3d_Buffer) anAttribs = new Graphic3d_Buffer (Graphic3d_Buffer::DefaultAllocator());
1185 if (!anAttribs->Init (myIndices->NbElements, myAttribs->AttributesArray(), myAttribs->NbAttributes))
1186 {
1187 return Standard_False; // failed to initialize attribute array
1188 }
1189
1190 for (Standard_Integer anIdxIdx = 0; anIdxIdx < myIndices->NbElements; ++anIdxIdx)
1191 {
1192 const Standard_Integer anIndex = myIndices->Index (anIdxIdx);
1193 memcpy (anAttribs->ChangeData() + myAttribs->Stride * anIdxIdx,
1194 myAttribs->Data() + myAttribs->Stride * anIndex,
1195 myAttribs->Stride);
1196 }
1197
1198 myIndices.Nullify();
1199 myAttribs = anAttribs;
1200 }
1201
1202 return Standard_True;
1203 }
1204
1205 // =======================================================================
1206 // function : InitBuffers
1207 // purpose :
1208 // =======================================================================
InitBuffers(const Handle (OpenGl_Context)& theContext,const Graphic3d_TypeOfPrimitiveArray theType,const Handle (Graphic3d_IndexBuffer)& theIndices,const Handle (Graphic3d_Buffer)& theAttribs,const Handle (Graphic3d_BoundBuffer)& theBounds)1209 void OpenGl_PrimitiveArray::InitBuffers (const Handle(OpenGl_Context)& theContext,
1210 const Graphic3d_TypeOfPrimitiveArray theType,
1211 const Handle(Graphic3d_IndexBuffer)& theIndices,
1212 const Handle(Graphic3d_Buffer)& theAttribs,
1213 const Handle(Graphic3d_BoundBuffer)& theBounds)
1214 {
1215 // Release old graphic resources
1216 Release (theContext.get());
1217
1218 myIndices = theIndices;
1219 myAttribs = theAttribs;
1220 myBounds = theBounds;
1221 #if defined(GL_ES_VERSION_2_0)
1222 processIndices (theContext);
1223 #endif
1224
1225 setDrawMode (theType);
1226 }
1227
1228 // =======================================================================
1229 // function : DumpJson
1230 // purpose :
1231 // =======================================================================
DumpJson(Standard_OStream & theOStream,Standard_Integer theDepth) const1232 void OpenGl_PrimitiveArray::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
1233 {
1234 OCCT_DUMP_CLASS_BEGIN (theOStream, OpenGl_PrimitiveArray)
1235
1236 OCCT_DUMP_BASE_CLASS (theOStream, theDepth, OpenGl_Element)
1237
1238 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myVboIndices.get())
1239 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myVboAttribs.get())
1240
1241 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myIndices.get())
1242 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myAttribs.get())
1243 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myBounds.get())
1244
1245 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDrawMode)
1246 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsFillType)
1247 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsVboInit)
1248 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myUID)
1249 }
1250