0024228: TKOpenGL - destroy GL context at view close
[occt.git] / src / OpenGl / OpenGl_PrimitiveArray.cxx
1 // Created on: 2011-07-13
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2013 OPEN CASCADE SAS
4 //
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.
9 //
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.
12 //
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.
19
20 #include <OpenGl_IndexBuffer.hxx>
21 #include <OpenGl_Context.hxx>
22
23 #include <OpenGl_PrimitiveArray.hxx>
24
25 #include <OpenGl_AspectFace.hxx>
26 #include <OpenGl_GraphicDriver.hxx>
27 #include <OpenGl_PointSprite.hxx>
28 #include <OpenGl_Structure.hxx>
29 #include <OpenGl_Workspace.hxx>
30
31 #include <InterfaceGraphic_PrimitiveArray.hxx>
32
33 // =======================================================================
34 // function : clearMemoryOwn
35 // purpose  :
36 // =======================================================================
37 void OpenGl_PrimitiveArray::clearMemoryOwn() const
38 {
39   Standard::Free ((Standard_Address& )myPArray->edges);
40   Standard::Free ((Standard_Address& )myPArray->vertices);
41   Standard::Free ((Standard_Address& )myPArray->vcolours);
42   Standard::Free ((Standard_Address& )myPArray->vnormals);
43   Standard::Free ((Standard_Address& )myPArray->vtexels);
44   Standard::Free ((Standard_Address& )myPArray->edge_vis); /// ???
45
46   myPArray->edges    = NULL;
47   myPArray->vertices = NULL;
48   myPArray->vcolours = NULL;
49   myPArray->vnormals = NULL;
50   myPArray->vtexels  = NULL;
51   myPArray->edge_vis = NULL;
52 }
53
54 // =======================================================================
55 // function : clearMemoryGL
56 // purpose  :
57 // =======================================================================
58 void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
59 {
60   for (Standard_Integer anIter = 0; anIter < VBOMaxType; ++anIter)
61   {
62     if (!myVbos[anIter].IsNull())
63     {
64       myVbos[anIter]->Release (theGlCtx.operator->());
65       myVbos[anIter].Nullify();
66     }
67   }
68 }
69
70 // =======================================================================
71 // function : BuildVBO
72 // purpose  :
73 // =======================================================================
74 Standard_Boolean OpenGl_PrimitiveArray::BuildVBO (const Handle(OpenGl_Workspace)& theWorkspace) const
75 {
76   const Handle(OpenGl_Context)& aGlCtx = theWorkspace->GetGlContext();
77   if (myPArray->vertices == NULL)
78   {
79     // vertices should be always defined - others are optional
80     return Standard_False;
81   }
82   myVbos[VBOVertices] = new OpenGl_VertexBuffer();
83   if (!myVbos[VBOVertices]->Init (aGlCtx, 3, myPArray->num_vertexs, &myPArray->vertices[0].xyz[0]))
84   {
85     clearMemoryGL (aGlCtx);
86     return Standard_False;
87   }
88
89   if (myPArray->edges != NULL
90    && myPArray->num_edges > 0)
91   {
92     myVbos[VBOEdges] = new OpenGl_IndexBuffer();
93     if (!myVbos[VBOEdges]->Init (aGlCtx, 1, myPArray->num_edges, (GLuint* )myPArray->edges))
94     {
95       clearMemoryGL (aGlCtx);
96       return Standard_False;
97     }
98   }
99   if (myPArray->vcolours != NULL)
100   {
101     myVbos[VBOVcolours] = new OpenGl_VertexBuffer();
102     if (!myVbos[VBOVcolours]->Init (aGlCtx, 4, myPArray->num_vertexs, (GLubyte* )myPArray->vcolours))
103     {
104       clearMemoryGL (aGlCtx);
105       return Standard_False;
106     }
107   }
108   if (myPArray->vnormals != NULL)
109   {
110     myVbos[VBOVnormals] = new OpenGl_VertexBuffer();
111     if (!myVbos[VBOVnormals]->Init (aGlCtx, 3, myPArray->num_vertexs, &myPArray->vnormals[0].xyz[0]))
112     {
113       clearMemoryGL (aGlCtx);
114       return Standard_False;
115     }
116   }
117   if (myPArray->vtexels)
118   {
119     myVbos[VBOVtexels] = new OpenGl_VertexBuffer();
120     if (!myVbos[VBOVtexels]->Init (aGlCtx, 2, myPArray->num_vertexs, &myPArray->vtexels[0].xy[0]))
121     {
122       clearMemoryGL (aGlCtx);
123       return Standard_False;
124     }
125   }
126
127   clearMemoryOwn();
128   return Standard_True;
129 }
130
131 // =======================================================================
132 // function : DrawArray
133 // purpose  :
134 // =======================================================================
135 void OpenGl_PrimitiveArray::DrawArray (Tint theLightingModel,
136                                        const Aspect_InteriorStyle theInteriorStyle,
137                                        Tint theEdgeFlag,
138                                        const TEL_COLOUR* theInteriorColour,
139                                        const TEL_COLOUR* theLineColour,
140                                        const TEL_COLOUR* theEdgeColour,
141                                        const OPENGL_SURF_PROP* theFaceProp,
142                                        const Handle(OpenGl_Workspace)& theWorkspace) const
143 {
144   const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
145
146   Tint i,n;
147   Tint transp = 0;
148   // Following pointers have been provided for performance improvement
149   tel_colour pfc = myPArray->fcolours;
150   Tint* pvc = myPArray->vcolours;
151   if (pvc != NULL)
152   {
153     for (i = 0; i < myPArray->num_vertexs; ++i)
154     {
155       transp = int(theFaceProp->trans * 255.0f);
156     #if defined (sparc) || defined (__sparc__) || defined (__sparc)
157       pvc[i] = (pvc[i] & 0xffffff00);
158       pvc[i] += transp;
159     #else
160       pvc[i] = (pvc[i] & 0x00ffffff);
161       pvc[i] += transp << 24;
162     #endif
163     }
164   }
165
166   switch (myPArray->type)
167   {
168     case TelPointsArrayType:
169     case TelPolylinesArrayType:
170     case TelSegmentsArrayType:
171       glColor3fv (theLineColour->rgb);
172       break;
173     case TelPolygonsArrayType:
174     case TelTrianglesArrayType:
175     case TelQuadranglesArrayType:
176     case TelTriangleStripsArrayType:
177     case TelQuadrangleStripsArrayType:
178     case TelTriangleFansArrayType:
179       glColor3fv (theInteriorColour->rgb);
180       break;
181   }
182
183   // Temporarily disable environment mapping
184   if (myDrawMode <= GL_LINE_STRIP)
185   {
186     glPushAttrib (GL_ENABLE_BIT);
187     glDisable (GL_TEXTURE_1D);
188     glDisable (GL_TEXTURE_2D);
189   }
190
191   if ((myDrawMode >  GL_LINE_STRIP && theInteriorStyle != Aspect_IS_EMPTY) ||
192       (myDrawMode <= GL_LINE_STRIP))
193   {
194     if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
195     {
196       pfc = NULL;
197       pvc = NULL;
198     }
199
200     if (theInteriorStyle == Aspect_IS_HIDDENLINE)
201     {
202       theEdgeFlag = 1;
203       pfc = NULL;
204       pvc = NULL;
205     }
206
207     // Sometimes the GL_LIGHTING mode is activated here
208     // without glEnable(GL_LIGHTING) call for an unknown reason, so it is necessary
209     // to call glEnable(GL_LIGHTING) to synchronize Light On/Off mechanism*
210     if (theLightingModel == 0 || myDrawMode <= GL_LINE_STRIP)
211       glDisable (GL_LIGHTING);
212     else
213       glEnable (GL_LIGHTING);
214
215     if (!toDrawVbo())
216     {
217       if (myPArray->vertices != NULL)
218       {
219         glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices
220         glEnableClientState (GL_VERTEX_ARRAY);
221       }
222       if (myPArray->vnormals != NULL)
223       {
224         glNormalPointer (GL_FLOAT, 0, myPArray->vnormals); // array of normals
225         glEnableClientState (GL_NORMAL_ARRAY);
226       }
227       if (myPArray->vtexels != NULL)
228       {
229         glTexCoordPointer (2, GL_FLOAT, 0, myPArray->vtexels); // array of texture coordinates
230         glEnableClientState (GL_TEXTURE_COORD_ARRAY);
231       }
232
233       if ((pvc != NULL) && (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) == 0)
234       {
235         glColorPointer (4, GL_UNSIGNED_BYTE, 0, pvc);  // array of colors
236         glEnableClientState (GL_COLOR_ARRAY);
237         glColorMaterial (GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
238         glEnable (GL_COLOR_MATERIAL);
239       }
240     }
241     else
242     {
243       // Bindings concrete pointer in accordance with VBO buffer
244       myVbos[VBOVertices]->BindFixed (aGlContext, GL_VERTEX_ARRAY);
245       if (!myVbos[VBOVnormals].IsNull())
246       {
247         myVbos[VBOVnormals]->BindFixed (aGlContext, GL_NORMAL_ARRAY);
248       }
249       if (!myVbos[VBOVtexels].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
250       {
251         myVbos[VBOVtexels]->BindFixed (aGlContext, GL_TEXTURE_COORD_ARRAY);
252       }
253       if (!myVbos[VBOVcolours].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) == 0)
254       {
255         myVbos[VBOVcolours]->BindFixed (aGlContext, GL_COLOR_ARRAY);
256         glColorMaterial (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
257         glEnable (GL_COLOR_MATERIAL);
258       }
259     }
260
261     /// OCC22236 NOTE: draw for all situations:
262     /// 1) draw elements from myPArray->bufferVBO[VBOEdges] indicies array
263     /// 2) draw elements from vertice array, when bounds defines count of primitive's verts.
264     /// 3) draw primitive by vertexes if no edges and bounds array is specified
265     if (toDrawVbo())
266     {
267       if (!myVbos[VBOEdges].IsNull())
268       {
269         myVbos[VBOEdges]->Bind (aGlContext);
270         if (myPArray->num_bounds > 0)
271         {
272           // draw primitives by vertex count with the indicies
273           Tint* anOffset = NULL;
274           for (i = 0; i < myPArray->num_bounds; ++i)
275           {
276             if (pfc != NULL) glColor3fv (pfc[i].rgb);
277             glDrawElements (myDrawMode, myPArray->bounds[i], myVbos[VBOEdges]->GetDataType(), anOffset);
278             anOffset += myPArray->bounds[i];
279           }
280         }
281         else
282         {
283           // draw one (or sequential) primitive by the indicies
284           glDrawElements (myDrawMode, myPArray->num_edges, myVbos[VBOEdges]->GetDataType(), NULL);
285         }
286         myVbos[VBOEdges]->Unbind (aGlContext);
287       }
288       else if (myPArray->num_bounds > 0)
289       {
290         for (i = n = 0; i < myPArray->num_bounds; ++i)
291         {
292           if (pfc != NULL) glColor3fv (pfc[i].rgb);
293           glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
294           n += myPArray->bounds[i];
295         }
296       }
297       else
298       {
299         if (myDrawMode == GL_POINTS)
300         {
301           DrawMarkers (theWorkspace);
302         }
303         else
304         {
305           glDrawArrays (myDrawMode, 0, myVbos[VBOVertices]->GetElemsNb());
306         }
307       }
308
309       // bind with 0
310       myVbos[VBOVertices]->UnbindFixed (aGlContext, GL_VERTEX_ARRAY);
311       if (!myVbos[VBOVnormals].IsNull())
312       {
313         myVbos[VBOVnormals]->UnbindFixed (aGlContext, GL_NORMAL_ARRAY);
314       }
315       if (!myVbos[VBOVtexels].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
316       {
317         myVbos[VBOVtexels]->UnbindFixed (aGlContext, GL_TEXTURE_COORD_ARRAY);
318       }
319       if (!myVbos[VBOVcolours].IsNull())
320       {
321         myVbos[VBOVcolours]->UnbindFixed (aGlContext, GL_COLOR_ARRAY);
322         glDisable (GL_COLOR_MATERIAL);
323         theWorkspace->NamedStatus |= OPENGL_NS_RESMAT; // Reset material
324       }
325     }
326     else
327     {
328       if (myPArray->num_bounds > 0)
329       {
330         if (myPArray->num_edges > 0)
331         {
332           for (i = n = 0; i < myPArray->num_bounds; ++i)
333           {
334             if (pfc != NULL) glColor3fv (pfc[i].rgb);
335             glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, (GLenum* )&myPArray->edges[n]);
336             n += myPArray->bounds[i];
337           }
338         }
339         else
340         {
341           for (i = n = 0; i < myPArray->num_bounds; ++i)
342           {
343             if (pfc != NULL) glColor3fv (pfc[i].rgb);
344             glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
345             n += myPArray->bounds[i];
346           }
347         }
348       }
349       else if (myPArray->num_edges > 0)
350       {
351         glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, (GLenum* )myPArray->edges);
352       }
353       else
354       {
355         if (myDrawMode == GL_POINTS)
356         {
357           DrawMarkers (theWorkspace);
358         }
359         else
360         {
361           glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
362         }
363       }
364
365       if (pvc != NULL)
366       {
367         glDisable (GL_COLOR_MATERIAL);
368         theWorkspace->NamedStatus |= OPENGL_NS_RESMAT; // Reset material
369       }
370
371       glDisableClientState (GL_VERTEX_ARRAY);
372       if (myPArray->vcolours != NULL)
373         glDisableClientState (GL_COLOR_ARRAY);
374       if (myPArray->vnormals != NULL)
375         glDisableClientState (GL_NORMAL_ARRAY);
376       if (myPArray->vtexels != NULL)
377         glDisableClientState (GL_TEXTURE_COORD_ARRAY);
378     }
379   }
380
381   // On some NVIDIA graphic cards, using glEdgeFlagPointer() in
382   // combination with VBO (edge flag data put into a VBO buffer)
383   // leads to a crash in a driver. Therefore, edge flags are simply
384   // igonored when VBOs are enabled, so all the edges are drawn if
385   // edge visibility is turned on. In order to draw edges selectively,
386   // either disable VBO or turn off edge visibilty in the current
387   // primitive array and create a separate primitive array (segments)
388   // and put edges to be drawn into it.
389   if (theEdgeFlag && myDrawMode > GL_LINE_STRIP)
390   {
391     DrawEdges (theEdgeColour, theWorkspace);
392   }
393
394   if (myDrawMode <= GL_LINE_STRIP)
395     glPopAttrib();
396 }
397
398 // =======================================================================
399 // function : DrawEdges
400 // purpose  :
401 // =======================================================================
402 void OpenGl_PrimitiveArray::DrawEdges (const TEL_COLOUR*               theEdgeColour,
403                                        const Handle(OpenGl_Workspace)& theWorkspace) const
404 {
405   glDisable (GL_LIGHTING);
406
407   const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
408   const OpenGl_AspectLine* anAspectLineOld = NULL;
409   if (myDrawMode > GL_LINE_STRIP)
410   {
411     anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge());
412     theWorkspace->AspectLine (Standard_True);
413
414     glPushAttrib (GL_POLYGON_BIT);
415     glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
416   }
417
418   Tint i, j, n;
419
420   /// OCC22236 NOTE: draw edges for all situations:
421   /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indicies array
422   /// 2) draw elements from vertice array, when bounds defines count of primitive's verts.
423   /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
424   if (toDrawVbo())
425   {
426     myVbos[VBOVertices]->BindFixed (aGlContext, GL_VERTEX_ARRAY);
427     glColor3fv (theEdgeColour->rgb);
428     if (!myVbos[VBOEdges].IsNull())
429     {
430       myVbos[VBOEdges]->Bind (aGlContext);
431
432       // draw primitives by vertex count with the indicies
433       if (myPArray->num_bounds > 0)
434       {
435         Tint* offset = 0;
436         for (i = 0, offset = 0; i < myPArray->num_bounds; ++i)
437         {
438           glDrawElements (myDrawMode, myPArray->bounds[i], myVbos[VBOEdges]->GetDataType(), offset);
439           offset += myPArray->bounds[i];
440         }
441       }
442       // draw one (or sequential) primitive by the indicies
443       else
444       {
445         glDrawElements (myDrawMode, myVbos[VBOEdges]->GetElemsNb(), myVbos[VBOEdges]->GetDataType(), NULL);
446       }
447       myVbos[VBOEdges]->Unbind (aGlContext);
448     }
449     else if (myPArray->num_bounds > 0)
450     {
451       for (i = n = 0; i < myPArray->num_bounds; ++i)
452       {
453         glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
454         n += myPArray->bounds[i];
455       }
456     }
457     else
458     {
459       glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
460     }
461
462     // unbind buffers
463     myVbos[VBOVertices]->UnbindFixed (aGlContext, GL_VERTEX_ARRAY);
464   }
465   else
466   {
467     glEnableClientState (GL_VERTEX_ARRAY);
468     glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices
469
470     glColor3fv (theEdgeColour->rgb);
471     if (myPArray->num_bounds > 0)
472     {
473       if (myPArray->num_edges > 0)
474       {
475         for (i = n = 0; i < myPArray->num_bounds; ++i)
476         {
477           if (myPArray->edge_vis)
478           {
479             glBegin (myDrawMode);
480             for (j = 0; j < myPArray->bounds[i]; ++j)
481             {
482               glEdgeFlag (myPArray->edge_vis[n+j]);
483               glVertex3fv (&myPArray->vertices[myPArray->edges[n+j]].xyz[0]);
484             }
485             glEnd();
486           }
487           else
488           {
489             glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, (GLenum* )&myPArray->edges[n]);
490           }
491           n += myPArray->bounds[i];
492         }
493       }
494       else
495       {
496         for (i = n = 0 ; i < myPArray->num_bounds; ++i)
497         {
498           glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
499           n += myPArray->bounds[i];
500         }
501       }
502     }
503     else if (myPArray->num_edges > 0)
504     {
505       if (myPArray->edge_vis)
506       {
507         glBegin (myDrawMode);
508         for (i = 0; i < myPArray->num_edges; ++i)
509         {
510           glEdgeFlag (myPArray->edge_vis[i]);
511           glVertex3fv (&myPArray->vertices[myPArray->edges[i]].xyz[0]);
512         }
513         glEnd();
514       }
515       else
516       {
517         glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, (GLenum* )myPArray->edges);
518       }
519     }
520     else
521     {
522       glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
523     }
524   }
525
526   if (myDrawMode > GL_LINE_STRIP)
527   {
528     // Restore line context
529     theWorkspace->SetAspectLine (anAspectLineOld);
530     glPopAttrib();
531   }
532 }
533
534 // =======================================================================
535 // function : DrawMarkers
536 // purpose  :
537 // =======================================================================
538 void OpenGl_PrimitiveArray::DrawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
539 {
540   const OpenGl_AspectMarker* anAspectMarker     = theWorkspace->AspectMarker (Standard_True);
541   const Handle(OpenGl_Context)&     aCtx        = theWorkspace->GetGlContext();
542   const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->Sprite(theWorkspace);
543   const Standard_Boolean            isHilight   = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT);
544   if (aCtx->IsGlGreaterEqual (2, 0)
545    && !aSpriteNorm.IsNull() && !aSpriteNorm->IsDisplayList())
546   {
547     // Textured markers will be drawn with the point sprites
548     glPointSize (anAspectMarker->MarkerSize());
549
550     Handle(OpenGl_Texture) aTextureBack;
551     if (anAspectMarker->Type() != Aspect_TOM_POINT)
552     {
553       const Handle(OpenGl_PointSprite)& aSprite = (isHilight && anAspectMarker->SpriteHighlight(theWorkspace)->IsValid())
554                                                 ? anAspectMarker->SpriteHighlight(theWorkspace)
555                                                 : aSpriteNorm;
556       aTextureBack = theWorkspace->EnableTexture (aSprite);
557
558       glEnable (GL_ALPHA_TEST);
559       glAlphaFunc (GL_GEQUAL, 0.1f);
560
561       glEnable (GL_BLEND);
562       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
563     }
564
565     glDrawArrays (myDrawMode, 0, toDrawVbo() ? myVbos[VBOVertices]->GetElemsNb() : myPArray->num_vertexs);
566
567     glDisable (GL_BLEND);
568     glDisable (GL_ALPHA_TEST);
569     if (anAspectMarker->Type() != Aspect_TOM_POINT)
570     {
571       theWorkspace->EnableTexture (aTextureBack);
572     }
573     glPointSize (1.0f);
574     return;
575   }
576
577   // Textured markers will be drawn with the glBitmap
578   if (anAspectMarker->Type() == Aspect_TOM_POINT
579    || anAspectMarker->Type() == Aspect_TOM_O_POINT)
580   {
581     const GLfloat aPntSize = anAspectMarker->Type() == Aspect_TOM_POINT
582                            ? anAspectMarker->MarkerSize()
583                            : 0.0f;
584     if (aPntSize > 0.0f)
585     {
586       glPointSize (aPntSize);
587     }
588     glDrawArrays (myDrawMode, 0, toDrawVbo() ? myVbos[VBOVertices]->GetElemsNb() : myPArray->num_vertexs);
589     if (aPntSize > 0.0f)
590     {
591       glPointSize (1.0f);
592     }
593   }
594
595   if (anAspectMarker->Type() != Aspect_TOM_POINT
596    && !aSpriteNorm.IsNull())
597   {
598     if (!isHilight && (myPArray->vcolours != NULL))
599     {
600       for (Standard_Integer anIter = 0; anIter < myPArray->num_vertexs; anIter++)
601       {
602         glColor4ubv ((GLubyte* )&myPArray->vcolours[anIter]);
603         glRasterPos3fv (myPArray->vertices[anIter].xyz);
604         aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
605       }
606     }
607     else
608     {
609       for (Standard_Integer anIter = 0; anIter < myPArray->num_vertexs; anIter++)
610       {
611         glRasterPos3fv (myPArray->vertices[anIter].xyz);
612         aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
613       }
614     }
615   }
616 }
617
618 // =======================================================================
619 // function : OpenGl_PrimitiveArray
620 // purpose  :
621 // =======================================================================
622 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (CALL_DEF_PARRAY* thePArray)
623 : myPArray (thePArray),
624   myDrawMode (DRAW_MODE_NONE),
625   myIsVboInit (Standard_False)
626 {
627   switch (myPArray->type)
628   {
629     case TelPointsArrayType:
630       myDrawMode = GL_POINTS;
631       break;
632     case TelPolylinesArrayType:
633       myDrawMode = GL_LINE_STRIP;
634       break;
635     case TelSegmentsArrayType:
636       myDrawMode = GL_LINES;
637       break;
638     case TelPolygonsArrayType:
639       myDrawMode = GL_POLYGON;
640       break;
641     case TelTrianglesArrayType:
642       myDrawMode = GL_TRIANGLES;
643       break;
644     case TelQuadranglesArrayType:
645       myDrawMode = GL_QUADS;
646       break;
647     case TelTriangleStripsArrayType:
648       myDrawMode = GL_TRIANGLE_STRIP;
649       break;
650     case TelQuadrangleStripsArrayType:
651       myDrawMode = GL_QUAD_STRIP;
652       break;
653     case TelTriangleFansArrayType:
654       myDrawMode = GL_TRIANGLE_FAN;
655       break;
656   }
657 }
658
659 // =======================================================================
660 // function : ~OpenGl_PrimitiveArray
661 // purpose  :
662 // =======================================================================
663 OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
664 {
665   //
666 }
667
668 // =======================================================================
669 // function : Release
670 // purpose  :
671 // =======================================================================
672 void OpenGl_PrimitiveArray::Release (const Handle(OpenGl_Context)& theContext)
673 {
674   for (Standard_Integer anIter = 0; anIter < VBOMaxType; ++anIter)
675   {
676     if (!myVbos[anIter].IsNull())
677     {
678       if (!theContext.IsNull())
679       {
680         theContext->DelayedRelease (myVbos[anIter]);
681       }
682       myVbos[anIter].Nullify();
683     }
684   }
685 }
686
687 // =======================================================================
688 // function : Render
689 // purpose  :
690 // =======================================================================
691 void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
692 {
693   if (myPArray == NULL || myDrawMode == DRAW_MODE_NONE || myPArray->num_vertexs <= 0)
694   {
695     return;
696   }
697
698   const OpenGl_AspectFace*   anAspectFace   = theWorkspace->AspectFace   (Standard_True);
699   const OpenGl_AspectLine*   anAspectLine   = theWorkspace->AspectLine   (Standard_True);
700   const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (myDrawMode == GL_POINTS);
701
702   // create VBOs on first render call
703   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
704   if (!myIsVboInit
705    && !aCtx->caps->vboDisable
706    && aCtx->core15 != NULL
707    && (myDrawMode != GL_POINTS || anAspectMarker->Sprite(theWorkspace).IsNull() || !anAspectMarker->Sprite(theWorkspace)->IsDisplayList()))
708   {
709     if (!BuildVBO (theWorkspace))
710     {
711       TCollection_ExtendedString aMsg;
712       aMsg += "VBO creation for Primitive Array has failed for ";
713       aMsg += myPArray->num_vertexs;
714       aMsg += " vertices. Out of memory?";
715       aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
716     }
717     myIsVboInit = Standard_True;
718   }
719
720   switch (myPArray->type)
721   {
722     case TelPointsArrayType:
723     case TelPolylinesArrayType:
724     case TelSegmentsArrayType:
725     {
726       glDisable (GL_LIGHTING);
727       break;
728     }
729     default:
730       break;
731   }
732
733   Tint aFrontLightingModel = anAspectFace->IntFront().color_mask;
734   const TEL_COLOUR* anInteriorColor = &anAspectFace->IntFront().matcol;
735   const TEL_COLOUR* anEdgeColor = &anAspectFace->AspectEdge()->Color();
736   const TEL_COLOUR* aLineColor = (myPArray->type == TelPointsArrayType) ? &anAspectMarker->Color() : &anAspectLine->Color();
737
738   // Use highlight colors
739   if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
740   {
741     anEdgeColor = anInteriorColor = aLineColor = theWorkspace->HighlightColor;
742     aFrontLightingModel = 0;
743   }
744
745   DrawArray (aFrontLightingModel,
746              anAspectFace->InteriorStyle(),
747              anAspectFace->Edge(),
748              anInteriorColor,
749              aLineColor,
750              anEdgeColor,
751              &anAspectFace->IntFront(),
752              theWorkspace);
753 }