1 // Created on: 2011-07-13
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2013 OPEN CASCADE SAS
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
20 #include <OpenGl_AspectFace.hxx>
21 #include <OpenGl_Context.hxx>
22 #include <OpenGl_GraphicDriver.hxx>
23 #include <OpenGl_IndexBuffer.hxx>
24 #include <OpenGl_PointSprite.hxx>
25 #include <OpenGl_PrimitiveArray.hxx>
26 #include <OpenGl_ShaderManager.hxx>
27 #include <OpenGl_ShaderProgram.hxx>
28 #include <OpenGl_Structure.hxx>
29 #include <OpenGl_Workspace.hxx>
31 #include <InterfaceGraphic_PrimitiveArray.hxx>
36 void BindProgramWithMaterial (const Handle(OpenGl_Workspace)& theWS,
39 const Handle(OpenGl_Context)& aCtx = theWS->GetGlContext();
40 const Handle(OpenGl_ShaderProgram)& aProgram = theAspect->ShaderProgramRes (theWS);
41 if (aProgram.IsNull())
43 OpenGl_ShaderProgram::Unbind (aCtx);
46 aProgram->BindWithVariables (aCtx);
48 const OpenGl_MaterialState* aMaterialState = aCtx->ShaderManager()->MaterialState (aProgram);
49 if (aMaterialState == NULL || aMaterialState->Aspect() != theAspect)
51 aCtx->ShaderManager()->UpdateMaterialStateTo (aProgram, theAspect);
54 aCtx->ShaderManager()->PushState (aProgram);
58 // =======================================================================
59 // function : clearMemoryOwn
61 // =======================================================================
62 void OpenGl_PrimitiveArray::clearMemoryOwn() const
64 Standard::Free ((Standard_Address& )myPArray->edges);
65 Standard::Free ((Standard_Address& )myPArray->vertices);
66 Standard::Free ((Standard_Address& )myPArray->vcolours);
67 Standard::Free ((Standard_Address& )myPArray->vnormals);
68 Standard::Free ((Standard_Address& )myPArray->vtexels);
69 Standard::Free ((Standard_Address& )myPArray->edge_vis); /// ???
71 myPArray->edges = NULL;
72 myPArray->vertices = NULL;
73 myPArray->vcolours = NULL;
74 myPArray->vnormals = NULL;
75 myPArray->vtexels = NULL;
76 myPArray->edge_vis = NULL;
79 // =======================================================================
80 // function : clearMemoryGL
82 // =======================================================================
83 void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
85 for (Standard_Integer anIter = 0; anIter < VBOMaxType; ++anIter)
87 if (!myVbos[anIter].IsNull())
89 myVbos[anIter]->Release (theGlCtx.operator->());
90 myVbos[anIter].Nullify();
95 // =======================================================================
96 // function : BuildVBO
98 // =======================================================================
99 Standard_Boolean OpenGl_PrimitiveArray::BuildVBO (const Handle(OpenGl_Workspace)& theWorkspace) const
101 const Handle(OpenGl_Context)& aGlCtx = theWorkspace->GetGlContext();
102 if (myPArray->vertices == NULL)
104 // vertices should be always defined - others are optional
105 return Standard_False;
107 myVbos[VBOVertices] = new OpenGl_VertexBuffer();
108 if (!myVbos[VBOVertices]->Init (aGlCtx, 3, myPArray->num_vertexs, &myPArray->vertices[0].xyz[0]))
110 clearMemoryGL (aGlCtx);
111 return Standard_False;
114 if (myPArray->edges != NULL
115 && myPArray->num_edges > 0)
117 myVbos[VBOEdges] = new OpenGl_IndexBuffer();
118 if (!myVbos[VBOEdges]->Init (aGlCtx, 1, myPArray->num_edges, (GLuint* )myPArray->edges))
120 clearMemoryGL (aGlCtx);
121 return Standard_False;
124 if (myPArray->vcolours != NULL)
126 myVbos[VBOVcolours] = new OpenGl_VertexBuffer();
127 if (!myVbos[VBOVcolours]->Init (aGlCtx, 4, myPArray->num_vertexs, (GLubyte* )myPArray->vcolours))
129 clearMemoryGL (aGlCtx);
130 return Standard_False;
133 if (myPArray->vnormals != NULL)
135 myVbos[VBOVnormals] = new OpenGl_VertexBuffer();
136 if (!myVbos[VBOVnormals]->Init (aGlCtx, 3, myPArray->num_vertexs, &myPArray->vnormals[0].xyz[0]))
138 clearMemoryGL (aGlCtx);
139 return Standard_False;
142 if (myPArray->vtexels)
144 myVbos[VBOVtexels] = new OpenGl_VertexBuffer();
145 if (!myVbos[VBOVtexels]->Init (aGlCtx, 2, myPArray->num_vertexs, &myPArray->vtexels[0].xy[0]))
147 clearMemoryGL (aGlCtx);
148 return Standard_False;
152 if (!aGlCtx->caps->keepArrayData)
157 return Standard_True;
160 // =======================================================================
161 // function : DrawArray
163 // =======================================================================
164 void OpenGl_PrimitiveArray::DrawArray (Tint theLightingModel,
165 const Aspect_InteriorStyle theInteriorStyle,
167 const TEL_COLOUR* theInteriorColour,
168 const TEL_COLOUR* theLineColour,
169 const TEL_COLOUR* theEdgeColour,
170 const OPENGL_SURF_PROP* theFaceProp,
171 const Handle(OpenGl_Workspace)& theWorkspace) const
173 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
177 // Following pointers have been provided for performance improvement
178 tel_colour pfc = myPArray->fcolours;
179 Tint* pvc = myPArray->vcolours;
182 for (i = 0; i < myPArray->num_vertexs; ++i)
184 transp = int(theFaceProp->trans * 255.0f);
185 #if defined (sparc) || defined (__sparc__) || defined (__sparc)
186 pvc[i] = (pvc[i] & 0xffffff00);
189 pvc[i] = (pvc[i] & 0x00ffffff);
190 pvc[i] += transp << 24;
195 switch (myPArray->type)
197 case TelPointsArrayType:
198 case TelPolylinesArrayType:
199 case TelSegmentsArrayType:
200 glColor3fv (theLineColour->rgb);
202 case TelPolygonsArrayType:
203 case TelTrianglesArrayType:
204 case TelQuadranglesArrayType:
205 case TelTriangleStripsArrayType:
206 case TelQuadrangleStripsArrayType:
207 case TelTriangleFansArrayType:
208 glColor3fv (theInteriorColour->rgb);
212 // Temporarily disable environment mapping
213 if (myDrawMode <= GL_LINE_STRIP)
215 glPushAttrib (GL_ENABLE_BIT);
216 glDisable (GL_TEXTURE_1D);
217 glDisable (GL_TEXTURE_2D);
220 if ((myDrawMode > GL_LINE_STRIP && theInteriorStyle != Aspect_IS_EMPTY) ||
221 (myDrawMode <= GL_LINE_STRIP))
223 if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
229 if (theInteriorStyle == Aspect_IS_HIDDENLINE)
236 // Sometimes the GL_LIGHTING mode is activated here
237 // without glEnable(GL_LIGHTING) call for an unknown reason, so it is necessary
238 // to call glEnable(GL_LIGHTING) to synchronize Light On/Off mechanism*
239 if (theLightingModel == 0 || myDrawMode <= GL_LINE_STRIP)
240 glDisable (GL_LIGHTING);
242 glEnable (GL_LIGHTING);
246 if (myPArray->vertices != NULL)
248 glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices
249 glEnableClientState (GL_VERTEX_ARRAY);
251 if (myPArray->vnormals != NULL)
253 glNormalPointer (GL_FLOAT, 0, myPArray->vnormals); // array of normals
254 glEnableClientState (GL_NORMAL_ARRAY);
256 if (myPArray->vtexels != NULL)
258 glTexCoordPointer (2, GL_FLOAT, 0, myPArray->vtexels); // array of texture coordinates
259 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
262 if ((pvc != NULL) && (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) == 0)
264 glColorPointer (4, GL_UNSIGNED_BYTE, 0, pvc); // array of colors
265 glEnableClientState (GL_COLOR_ARRAY);
266 glColorMaterial (GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
267 glEnable (GL_COLOR_MATERIAL);
272 // Bindings concrete pointer in accordance with VBO buffer
273 myVbos[VBOVertices]->BindFixed (aGlContext, GL_VERTEX_ARRAY);
274 if (!myVbos[VBOVnormals].IsNull())
276 myVbos[VBOVnormals]->BindFixed (aGlContext, GL_NORMAL_ARRAY);
278 if (!myVbos[VBOVtexels].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
280 myVbos[VBOVtexels]->BindFixed (aGlContext, GL_TEXTURE_COORD_ARRAY);
282 if (!myVbos[VBOVcolours].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) == 0)
284 myVbos[VBOVcolours]->BindFixed (aGlContext, GL_COLOR_ARRAY);
285 glColorMaterial (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
286 glEnable (GL_COLOR_MATERIAL);
290 /// OCC22236 NOTE: draw for all situations:
291 /// 1) draw elements from myPArray->bufferVBO[VBOEdges] indicies array
292 /// 2) draw elements from vertice array, when bounds defines count of primitive's verts.
293 /// 3) draw primitive by vertexes if no edges and bounds array is specified
296 if (!myVbos[VBOEdges].IsNull())
298 myVbos[VBOEdges]->Bind (aGlContext);
299 if (myPArray->num_bounds > 0)
301 // draw primitives by vertex count with the indicies
302 Tint* anOffset = NULL;
303 for (i = 0; i < myPArray->num_bounds; ++i)
305 if (pfc != NULL) glColor3fv (pfc[i].rgb);
306 glDrawElements (myDrawMode, myPArray->bounds[i], myVbos[VBOEdges]->GetDataType(), anOffset);
307 anOffset += myPArray->bounds[i];
312 // draw one (or sequential) primitive by the indicies
313 glDrawElements (myDrawMode, myPArray->num_edges, myVbos[VBOEdges]->GetDataType(), NULL);
315 myVbos[VBOEdges]->Unbind (aGlContext);
317 else if (myPArray->num_bounds > 0)
319 for (i = n = 0; i < myPArray->num_bounds; ++i)
321 if (pfc != NULL) glColor3fv (pfc[i].rgb);
322 glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
323 n += myPArray->bounds[i];
328 if (myDrawMode == GL_POINTS)
330 DrawMarkers (theWorkspace);
334 glDrawArrays (myDrawMode, 0, myVbos[VBOVertices]->GetElemsNb());
339 myVbos[VBOVertices]->UnbindFixed (aGlContext, GL_VERTEX_ARRAY);
340 if (!myVbos[VBOVnormals].IsNull())
342 myVbos[VBOVnormals]->UnbindFixed (aGlContext, GL_NORMAL_ARRAY);
344 if (!myVbos[VBOVtexels].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
346 myVbos[VBOVtexels]->UnbindFixed (aGlContext, GL_TEXTURE_COORD_ARRAY);
348 if (!myVbos[VBOVcolours].IsNull())
350 myVbos[VBOVcolours]->UnbindFixed (aGlContext, GL_COLOR_ARRAY);
351 glDisable (GL_COLOR_MATERIAL);
352 theWorkspace->NamedStatus |= OPENGL_NS_RESMAT; // Reset material
357 if (myPArray->num_bounds > 0)
359 if (myPArray->num_edges > 0)
361 for (i = n = 0; i < myPArray->num_bounds; ++i)
363 if (pfc != NULL) glColor3fv (pfc[i].rgb);
364 glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, (GLenum* )&myPArray->edges[n]);
365 n += myPArray->bounds[i];
370 for (i = n = 0; i < myPArray->num_bounds; ++i)
372 if (pfc != NULL) glColor3fv (pfc[i].rgb);
373 glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
374 n += myPArray->bounds[i];
378 else if (myPArray->num_edges > 0)
380 glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, (GLenum* )myPArray->edges);
384 if (myDrawMode == GL_POINTS)
386 DrawMarkers (theWorkspace);
390 glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
396 glDisable (GL_COLOR_MATERIAL);
397 theWorkspace->NamedStatus |= OPENGL_NS_RESMAT; // Reset material
400 glDisableClientState (GL_VERTEX_ARRAY);
401 if (myPArray->vcolours != NULL)
402 glDisableClientState (GL_COLOR_ARRAY);
403 if (myPArray->vnormals != NULL)
404 glDisableClientState (GL_NORMAL_ARRAY);
405 if (myPArray->vtexels != NULL)
406 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
410 // On some NVIDIA graphic cards, using glEdgeFlagPointer() in
411 // combination with VBO (edge flag data put into a VBO buffer)
412 // leads to a crash in a driver. Therefore, edge flags are simply
413 // igonored when VBOs are enabled, so all the edges are drawn if
414 // edge visibility is turned on. In order to draw edges selectively,
415 // either disable VBO or turn off edge visibilty in the current
416 // primitive array and create a separate primitive array (segments)
417 // and put edges to be drawn into it.
418 if (theEdgeFlag && myDrawMode > GL_LINE_STRIP)
420 DrawEdges (theEdgeColour, theWorkspace);
423 if (myDrawMode <= GL_LINE_STRIP)
427 // =======================================================================
428 // function : DrawEdges
430 // =======================================================================
431 void OpenGl_PrimitiveArray::DrawEdges (const TEL_COLOUR* theEdgeColour,
432 const Handle(OpenGl_Workspace)& theWorkspace) const
434 glDisable (GL_LIGHTING);
436 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
437 const OpenGl_AspectLine* anAspectLineOld = NULL;
438 if (myDrawMode > GL_LINE_STRIP)
440 anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge());
441 const OpenGl_AspectLine* anAspect = theWorkspace->AspectLine (Standard_True);
443 glPushAttrib (GL_POLYGON_BIT);
444 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
446 if (aGlContext->IsGlGreaterEqual (2, 0))
448 BindProgramWithMaterial (theWorkspace, anAspect);
454 /// OCC22236 NOTE: draw edges for all situations:
455 /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indicies array
456 /// 2) draw elements from vertice array, when bounds defines count of primitive's verts.
457 /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
460 myVbos[VBOVertices]->BindFixed (aGlContext, GL_VERTEX_ARRAY);
461 glColor3fv (theEdgeColour->rgb);
462 if (!myVbos[VBOEdges].IsNull())
464 myVbos[VBOEdges]->Bind (aGlContext);
466 // draw primitives by vertex count with the indicies
467 if (myPArray->num_bounds > 0)
470 for (i = 0, offset = 0; i < myPArray->num_bounds; ++i)
472 glDrawElements (myDrawMode, myPArray->bounds[i], myVbos[VBOEdges]->GetDataType(), offset);
473 offset += myPArray->bounds[i];
476 // draw one (or sequential) primitive by the indicies
479 glDrawElements (myDrawMode, myVbos[VBOEdges]->GetElemsNb(), myVbos[VBOEdges]->GetDataType(), NULL);
481 myVbos[VBOEdges]->Unbind (aGlContext);
483 else if (myPArray->num_bounds > 0)
485 for (i = n = 0; i < myPArray->num_bounds; ++i)
487 glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
488 n += myPArray->bounds[i];
493 glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
497 myVbos[VBOVertices]->UnbindFixed (aGlContext, GL_VERTEX_ARRAY);
501 glEnableClientState (GL_VERTEX_ARRAY);
502 glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices
504 glColor3fv (theEdgeColour->rgb);
505 if (myPArray->num_bounds > 0)
507 if (myPArray->num_edges > 0)
509 for (i = n = 0; i < myPArray->num_bounds; ++i)
511 if (myPArray->edge_vis)
513 glBegin (myDrawMode);
514 for (j = 0; j < myPArray->bounds[i]; ++j)
516 glEdgeFlag (myPArray->edge_vis[n+j]);
517 glVertex3fv (&myPArray->vertices[myPArray->edges[n+j]].xyz[0]);
523 glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, (GLenum* )&myPArray->edges[n]);
525 n += myPArray->bounds[i];
530 for (i = n = 0 ; i < myPArray->num_bounds; ++i)
532 glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
533 n += myPArray->bounds[i];
537 else if (myPArray->num_edges > 0)
539 if (myPArray->edge_vis)
541 glBegin (myDrawMode);
542 for (i = 0; i < myPArray->num_edges; ++i)
544 glEdgeFlag (myPArray->edge_vis[i]);
545 glVertex3fv (&myPArray->vertices[myPArray->edges[i]].xyz[0]);
551 glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, (GLenum* )myPArray->edges);
556 glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
560 if (myDrawMode > GL_LINE_STRIP)
562 // Restore line context
563 theWorkspace->SetAspectLine (anAspectLineOld);
568 // =======================================================================
569 // function : DrawMarkers
571 // =======================================================================
572 void OpenGl_PrimitiveArray::DrawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
574 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (Standard_True);
575 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
576 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (theWorkspace);
577 const Standard_Boolean isHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT);
578 if (aCtx->IsGlGreaterEqual (2, 0)
579 && !aSpriteNorm.IsNull() && !aSpriteNorm->IsDisplayList())
581 // Textured markers will be drawn with the point sprites
582 glPointSize (anAspectMarker->MarkerSize());
584 Handle(OpenGl_Texture) aTextureBack;
585 if (anAspectMarker->Type() != Aspect_TOM_POINT)
587 const Handle(OpenGl_PointSprite)& aSprite = (isHilight && anAspectMarker->SpriteHighlightRes (theWorkspace)->IsValid())
588 ? anAspectMarker->SpriteHighlightRes (theWorkspace)
590 aTextureBack = theWorkspace->EnableTexture (aSprite);
592 glEnable (GL_ALPHA_TEST);
593 glAlphaFunc (GL_GEQUAL, 0.1f);
596 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
599 glDrawArrays (myDrawMode, 0, toDrawVbo() ? myVbos[VBOVertices]->GetElemsNb() : myPArray->num_vertexs);
601 glDisable (GL_BLEND);
602 glDisable (GL_ALPHA_TEST);
603 if (anAspectMarker->Type() != Aspect_TOM_POINT)
605 theWorkspace->EnableTexture (aTextureBack);
611 // Textured markers will be drawn with the glBitmap
612 if (anAspectMarker->Type() == Aspect_TOM_POINT
613 || anAspectMarker->Type() == Aspect_TOM_O_POINT)
615 const GLfloat aPntSize = anAspectMarker->Type() == Aspect_TOM_POINT
616 ? anAspectMarker->MarkerSize()
620 glPointSize (aPntSize);
622 glDrawArrays (myDrawMode, 0, toDrawVbo() ? myVbos[VBOVertices]->GetElemsNb() : myPArray->num_vertexs);
629 if (anAspectMarker->Type() != Aspect_TOM_POINT
630 && !aSpriteNorm.IsNull())
632 if (!isHilight && (myPArray->vcolours != NULL))
634 for (Standard_Integer anIter = 0; anIter < myPArray->num_vertexs; anIter++)
636 glColor4ubv ((GLubyte* )&myPArray->vcolours[anIter]);
637 glRasterPos3fv (myPArray->vertices[anIter].xyz);
638 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
643 for (Standard_Integer anIter = 0; anIter < myPArray->num_vertexs; anIter++)
645 glRasterPos3fv (myPArray->vertices[anIter].xyz);
646 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
652 // =======================================================================
653 // function : OpenGl_PrimitiveArray
655 // =======================================================================
656 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (CALL_DEF_PARRAY* thePArray)
657 : myPArray (thePArray),
658 myDrawMode (DRAW_MODE_NONE),
659 myIsVboInit (Standard_False)
661 switch (myPArray->type)
663 case TelPointsArrayType:
664 myDrawMode = GL_POINTS;
666 case TelPolylinesArrayType:
667 myDrawMode = GL_LINE_STRIP;
669 case TelSegmentsArrayType:
670 myDrawMode = GL_LINES;
672 case TelPolygonsArrayType:
673 myDrawMode = GL_POLYGON;
675 case TelTrianglesArrayType:
676 myDrawMode = GL_TRIANGLES;
678 case TelQuadranglesArrayType:
679 myDrawMode = GL_QUADS;
681 case TelTriangleStripsArrayType:
682 myDrawMode = GL_TRIANGLE_STRIP;
684 case TelQuadrangleStripsArrayType:
685 myDrawMode = GL_QUAD_STRIP;
687 case TelTriangleFansArrayType:
688 myDrawMode = GL_TRIANGLE_FAN;
693 // =======================================================================
694 // function : ~OpenGl_PrimitiveArray
696 // =======================================================================
697 OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
702 // =======================================================================
703 // function : Release
705 // =======================================================================
706 void OpenGl_PrimitiveArray::Release (const Handle(OpenGl_Context)& theContext)
708 for (Standard_Integer anIter = 0; anIter < VBOMaxType; ++anIter)
710 if (!myVbos[anIter].IsNull())
712 if (!theContext.IsNull())
714 theContext->DelayedRelease (myVbos[anIter]);
716 myVbos[anIter].Nullify();
721 // =======================================================================
724 // =======================================================================
725 void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
727 if (myPArray == NULL || myDrawMode == DRAW_MODE_NONE || myPArray->num_vertexs <= 0)
732 const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace (Standard_True);
733 const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True);
734 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (myDrawMode == GL_POINTS);
736 // create VBOs on first render call
737 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
739 && !aCtx->caps->vboDisable
740 && aCtx->core15 != NULL
741 && (myDrawMode != GL_POINTS || anAspectMarker->SpriteRes (theWorkspace).IsNull() || !anAspectMarker->SpriteRes (theWorkspace)->IsDisplayList()))
743 if (!BuildVBO (theWorkspace))
745 TCollection_ExtendedString aMsg;
746 aMsg += "VBO creation for Primitive Array has failed for ";
747 aMsg += myPArray->num_vertexs;
748 aMsg += " vertices. Out of memory?";
749 aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
751 myIsVboInit = Standard_True;
754 switch (myPArray->type)
756 case TelPointsArrayType:
757 case TelPolylinesArrayType:
758 case TelSegmentsArrayType:
760 glDisable (GL_LIGHTING);
767 Tint aFrontLightingModel = anAspectFace->IntFront().color_mask;
768 const TEL_COLOUR* anInteriorColor = &anAspectFace->IntFront().matcol;
769 const TEL_COLOUR* anEdgeColor = &anAspectFace->AspectEdge()->Color();
770 const TEL_COLOUR* aLineColor = (myPArray->type == TelPointsArrayType) ? &anAspectMarker->Color() : &anAspectLine->Color();
772 // Use highlight colors
773 if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
775 anEdgeColor = anInteriorColor = aLineColor = theWorkspace->HighlightColor;
776 aFrontLightingModel = 0;
779 if (aCtx->IsGlGreaterEqual (2, 0))
781 switch (myPArray->type)
783 case TelPointsArrayType:
785 BindProgramWithMaterial (theWorkspace, anAspectMarker);
788 case TelSegmentsArrayType:
789 case TelPolylinesArrayType:
791 BindProgramWithMaterial (theWorkspace, anAspectLine);
794 default: // polygonal array
796 BindProgramWithMaterial (theWorkspace, anAspectFace);
802 DrawArray (aFrontLightingModel,
803 anAspectFace->InteriorStyle(),
804 anAspectFace->Edge(),
808 &anAspectFace->IntFront(),