0022734: Memory allocation error in OpenGl
[occt.git] / src / OpenGl / OpenGl_PrimitiveArray.cxx
1 // Created on: 2011-07-13
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2012 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
21 #include <OpenGl_ArbVBO.hxx>
22 #include <OpenGl_Context.hxx>
23
24 #include <OpenGl_PrimitiveArray.hxx>
25
26 #include <OpenGl_AspectFace.hxx>
27 #include <OpenGl_GraphicDriver.hxx>
28 #include <OpenGl_ResourceCleaner.hxx>
29 #include <OpenGl_ResourceVBO.hxx>
30 #include <OpenGl_Structure.hxx>
31 #include <OpenGl_TextureBox.hxx>
32
33 #include <InterfaceGraphic_PrimitiveArray.hxx>
34
35 enum
36 {
37   VBO_NOT_INITIALIZED = -1,
38   VBO_ERROR           =  0,
39   VBO_OK              =  1
40 };
41
42 namespace
43 {
44   static unsigned long vRand = 1L;
45   #define OGL_Rand() (vRand = vRand * 214013L + 2531011L)
46 };
47
48 // =======================================================================
49 // function : clearMemoryOwn
50 // purpose  :
51 // =======================================================================
52 void OpenGl_PrimitiveArray::clearMemoryOwn() const
53 {
54   if (myPArray->bufferVBO[VBOEdges] != 0)
55   {
56     Standard::Free ((Standard_Address& )myPArray->edges);
57     myPArray->edges = NULL;
58   }
59   if (myPArray->bufferVBO[VBOVertices] != 0)
60   {
61     Standard::Free ((Standard_Address& )myPArray->vertices);
62     myPArray->vertices = NULL;
63   }
64   if (myPArray->bufferVBO[VBOVcolours] != 0)
65   {
66     Standard::Free ((Standard_Address& )myPArray->vcolours);
67     myPArray->vcolours = NULL;
68   }
69   if (myPArray->bufferVBO[VBOVnormals] != 0)
70   {
71     Standard::Free ((Standard_Address& )myPArray->vnormals);
72     myPArray->vnormals = NULL;
73   }
74   if (myPArray->bufferVBO[VBOVtexels] != 0)
75   {
76     Standard::Free ((Standard_Address& )myPArray->vtexels);
77     myPArray->vtexels = NULL;
78   }
79   if (myPArray->edge_vis != NULL) /// ????
80   {
81     Standard::Free ((Standard_Address& )myPArray->edge_vis);
82     myPArray->edge_vis = NULL;
83   }
84 }
85
86 // =======================================================================
87 // function : clearMemoryGL
88 // purpose  :
89 // =======================================================================
90 void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlContext) const
91 {
92   if (myPArray->bufferVBO[VBOEdges] != 0)
93   {
94     theGlContext->arbVBO->glDeleteBuffersARB (1, &myPArray->bufferVBO[VBOEdges]);
95   }
96   if (myPArray->bufferVBO[VBOVertices] != 0)
97   {
98     theGlContext->arbVBO->glDeleteBuffersARB (1, &myPArray->bufferVBO[VBOVertices]);
99   }
100   if (myPArray->bufferVBO[VBOVcolours] != 0)
101   {
102     theGlContext->arbVBO->glDeleteBuffersARB (1, &myPArray->bufferVBO[VBOVcolours]);
103   }
104   if (myPArray->bufferVBO[VBOVnormals] != 0)
105   {
106     theGlContext->arbVBO->glDeleteBuffersARB (1, &myPArray->bufferVBO[VBOVnormals]);
107   } 
108   if (myPArray->bufferVBO[VBOVtexels] != 0)
109   {
110     theGlContext->arbVBO->glDeleteBuffersARB (1, &myPArray->bufferVBO[VBOVtexels]);
111   }
112   theGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
113   theGlContext->arbVBO->glBindBufferARB (GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
114 }
115
116 // =======================================================================
117 // function : checkSizeForGraphicMemory
118 // purpose  :
119 // =======================================================================
120 Standard_Boolean OpenGl_PrimitiveArray::checkSizeForGraphicMemory (const Handle(OpenGl_Context)& theGlContext) const
121 {
122   if (glGetError() == GL_OUT_OF_MEMORY)
123   {
124     myPArray->flagBufferVBO = VBO_ERROR;
125     clearMemoryGL (theGlContext);
126   }
127   else
128   {
129     myPArray->flagBufferVBO = VBO_OK;
130   }
131   return myPArray->flagBufferVBO == VBO_OK;
132 }
133
134 // =======================================================================
135 // function : BuildVBO
136 // purpose  :
137 // =======================================================================
138 Standard_Boolean OpenGl_PrimitiveArray::BuildVBO (const Handle(OpenGl_Workspace)& theWorkspace) const
139 {
140   int size_reqd = 0;
141   const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
142   if (myPArray->edges != NULL)
143   {
144     size_reqd = myPArray->num_edges * sizeof(Tint);
145     aGlContext->arbVBO->glGenBuffersARB (1, &myPArray->bufferVBO[VBOEdges]);   
146     aGlContext->arbVBO->glBindBufferARB (GL_ELEMENT_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOEdges]);
147     aGlContext->arbVBO->glBufferDataARB (GL_ELEMENT_ARRAY_BUFFER_ARB, size_reqd, myPArray->edges, GL_STATIC_DRAW_ARB);
148     if (!checkSizeForGraphicMemory (aGlContext))
149       return Standard_False;
150   }
151
152   if (myPArray->vertices != NULL)
153   {
154     size_reqd = myPArray->num_vertexs * sizeof(TEL_POINT);
155     aGlContext->arbVBO->glGenBuffersARB (1, &myPArray->bufferVBO[VBOVertices]);
156     aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVertices]);
157     aGlContext->arbVBO->glBufferDataARB (GL_ARRAY_BUFFER_ARB, size_reqd, myPArray->vertices, GL_STATIC_DRAW_ARB);
158     if (!checkSizeForGraphicMemory (aGlContext))
159       return Standard_False;
160   }
161
162   if (myPArray->vcolours != NULL)
163   {
164     size_reqd = myPArray->num_vertexs * sizeof(Tint);
165     aGlContext->arbVBO->glGenBuffersARB (1, &myPArray->bufferVBO[VBOVcolours]);
166     aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVcolours]); 
167     aGlContext->arbVBO->glBufferDataARB (GL_ARRAY_BUFFER_ARB, size_reqd, myPArray->vcolours, GL_STATIC_DRAW_ARB);
168     if (!checkSizeForGraphicMemory (aGlContext))
169       return Standard_False;
170   }
171
172   if (myPArray->vnormals != NULL)
173   {
174     size_reqd = myPArray->num_vertexs * sizeof(TEL_POINT);
175     aGlContext->arbVBO->glGenBuffersARB (1, &myPArray->bufferVBO[VBOVnormals]);
176     aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVnormals]);
177     aGlContext->arbVBO->glBufferDataARB (GL_ARRAY_BUFFER_ARB, size_reqd, myPArray->vnormals, GL_STATIC_DRAW_ARB);
178     if (!checkSizeForGraphicMemory (aGlContext))
179       return Standard_False;
180   }
181
182   if (myPArray->vtexels)
183   {
184     size_reqd = myPArray->num_vertexs * sizeof(TEL_TEXTURE_COORD);
185     aGlContext->arbVBO->glGenBuffersARB (1, &myPArray->bufferVBO[VBOVtexels]);
186     aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVtexels]);
187     aGlContext->arbVBO->glBufferDataARB (GL_ARRAY_BUFFER_ARB, size_reqd, myPArray->vtexels, GL_STATIC_DRAW_ARB);
188     if (!checkSizeForGraphicMemory (aGlContext))
189       return Standard_False;
190   }
191
192   if (myPArray->flagBufferVBO == VBO_OK)
193     clearMemoryOwn();
194
195   // specify context for VBO resource
196   myPArray->contextId = (Standard_Address )theWorkspace->GetGContext();
197   return Standard_True;
198 }
199
200 // =======================================================================
201 // function : DrawArrays
202 // purpose  : Auxiliary method to split Feedback/Normal rendering modes
203 // =======================================================================
204 inline void DrawArrays (const Handle(OpenGl_Workspace)& theWorkspace,
205                         const CALL_DEF_PARRAY* thePArray,
206                         const Standard_Boolean theIsFeedback,
207                         GLenum  theMode,
208                         GLint   theFirst,
209                         GLsizei theCount)
210 {
211   if (!theIsFeedback)
212   {
213     glDrawArrays (theMode, theFirst, theCount);
214     return;
215   }
216
217   glBegin (theMode);
218   for (int anIter = theFirst; anIter < (theFirst + theCount); ++anIter)
219   {
220     if (thePArray->vnormals != NULL)
221       glNormal3fv (thePArray->vnormals[anIter].xyz);
222     if (thePArray->vtexels  != NULL && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
223       glTexCoord3fv (thePArray->vtexels[anIter].xy);
224     if (thePArray->vertices != NULL)
225       glVertex3fv (thePArray->vertices[anIter].xyz);
226     if (thePArray->vcolours != NULL)
227       glColor4ubv((GLubyte* )thePArray->vcolours[anIter]);
228   }
229   glEnd();
230 }
231
232 // =======================================================================
233 // function : DrawElements
234 // purpose  : Auxiliary method to split Feedback/Normal rendering modes
235 // =======================================================================
236 inline void DrawElements (const Handle(OpenGl_Workspace)& theWorkspace,
237                           const CALL_DEF_PARRAY* thePArray,
238                           const Standard_Boolean theIsFeedback,
239                           GLenum  theMode,
240                           GLsizei theCount,
241                           GLenum* theIndices)
242 {
243   if (!theIsFeedback)
244   {
245     glDrawElements (theMode, theCount, GL_UNSIGNED_INT, theIndices);
246     return;
247   }
248
249   GLenum anIndex;
250   glBegin (theMode);
251   for (GLsizei anIter = 0; anIter < theCount; ++anIter)
252   {
253     anIndex = theIndices[anIter];
254     if (thePArray->vnormals != NULL)
255       glNormal3fv (thePArray->vnormals[anIndex].xyz);
256     if (thePArray->vtexels != NULL && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
257       glTexCoord3fv (thePArray->vtexels[anIndex].xy);
258     if (thePArray->vertices != NULL)
259       glVertex3fv (thePArray->vertices[anIndex].xyz);
260     if (thePArray->vcolours != NULL)
261       glColor4ubv ((GLubyte* )thePArray->vcolours[anIndex]);
262   }
263   glEnd();
264 }
265
266 // =======================================================================
267 // function : DrawArray
268 // purpose  :
269 // =======================================================================
270 void OpenGl_PrimitiveArray::DrawArray (Tint theLightingModel,
271                                        const Aspect_InteriorStyle theInteriorStyle,
272                                        Tint theEdgeFlag,
273                                        const TEL_COLOUR* theInteriorColour,
274                                        const TEL_COLOUR* theLineColour,
275                                        const TEL_COLOUR* theEdgeColour,
276                                        const OPENGL_SURF_PROP* theFaceProp,
277                                        const Handle(OpenGl_Workspace)& theWorkspace) const
278 {
279   const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
280
281   Tint i,n;
282   Tint transp = 0;
283   GLint renderMode;
284   // Following pointers have been provided for performance improvement
285   tel_colour pfc = myPArray->fcolours;
286   Tint* pvc = myPArray->vcolours;
287   if (pvc != NULL)
288   {
289     for (i = 0; i < myPArray->num_vertexs; ++i)
290     {
291       transp = int(theFaceProp->trans * 255.0f);
292     #if defined (sparc) || defined (__sparc__) || defined (__sparc) 
293       pvc[i] = (pvc[i] & 0xffffff00);
294       pvc[i] += transp;
295     #else     
296       pvc[i] = (pvc[i] & 0x00ffffff);
297       pvc[i] += transp << 24;
298     #endif
299     }
300   }
301
302   switch (myPArray->type)
303   {
304     case TelPointsArrayType:
305     case TelPolylinesArrayType:
306     case TelSegmentsArrayType:
307       glColor3fv (theLineColour->rgb);
308       break;
309     case TelPolygonsArrayType:
310     case TelTrianglesArrayType:
311     case TelQuadranglesArrayType:
312     case TelTriangleStripsArrayType:
313     case TelQuadrangleStripsArrayType:
314     case TelTriangleFansArrayType:
315       glColor3fv (theInteriorColour->rgb);
316       break;
317   }
318
319   // Temporarily disable environment mapping
320   if (myDrawMode <= GL_LINE_STRIP)
321   {
322     glPushAttrib (GL_ENABLE_BIT);
323     glDisable (GL_TEXTURE_1D);
324     glDisable (GL_TEXTURE_2D);
325   }
326
327   if (theWorkspace->DegenerateModel < 2 &&
328      ((myDrawMode >  GL_LINE_STRIP && theInteriorStyle != Aspect_IS_EMPTY) ||
329       (myDrawMode <= GL_LINE_STRIP)))
330   {
331     if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
332     {
333       pfc = NULL;
334       pvc = NULL;
335     }
336
337     if (theInteriorStyle == Aspect_IS_HIDDENLINE)
338     {
339       theEdgeFlag = 1;
340       pfc = NULL;
341       pvc = NULL;
342     }
343
344     // Sometimes the GL_LIGHTING mode is activated here
345     // without glEnable(GL_LIGHTING) call for an unknown reason, so it is necessary 
346     // to call glEnable(GL_LIGHTING) to synchronize Light On/Off mechanism*
347     if (theLightingModel == 0 || myDrawMode <= GL_LINE_STRIP)
348       glDisable (GL_LIGHTING);
349     else
350       glEnable (GL_LIGHTING);
351
352     glGetIntegerv (GL_RENDER_MODE, &renderMode);
353
354     if (myPArray->num_vertexs > 0
355      && myPArray->flagBufferVBO != VBO_OK
356      && renderMode != GL_FEEDBACK)
357     {
358       if (myPArray->vertices != NULL)
359       {
360         glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices
361         glEnableClientState (GL_VERTEX_ARRAY);
362       }
363       if (myPArray->vnormals != NULL)
364       {
365         glNormalPointer (GL_FLOAT, 0, myPArray->vnormals); // array of normals
366         glEnableClientState (GL_NORMAL_ARRAY);
367       }
368       if (myPArray->vtexels != NULL)
369       {
370         glTexCoordPointer (2, GL_FLOAT, 0, myPArray->vtexels); // array of texture coordinates
371         glEnableClientState (GL_TEXTURE_COORD_ARRAY);
372       }
373
374       if (pvc != NULL)
375       {
376         glColorPointer (4, GL_UNSIGNED_BYTE, 0, pvc);  // array of colors
377         glEnableClientState (GL_COLOR_ARRAY);
378         glColorMaterial (GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
379         glEnable (GL_COLOR_MATERIAL);
380       }
381     }
382     else if (myPArray->num_vertexs > 0
383           && myPArray->flagBufferVBO == VBO_OK)
384     {
385       // Bindings concrete pointer in accordance with VBO buffer
386       if (myPArray->bufferVBO[VBOVertices] != 0)
387       {
388         aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVertices]);
389         glVertexPointer (3, GL_FLOAT, 0, NULL); // array of vertices 
390         glEnableClientState (GL_VERTEX_ARRAY);
391       }
392       if (myPArray->bufferVBO[VBOVnormals] != 0)
393       {
394         aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVnormals]);
395         glNormalPointer (GL_FLOAT, 0, NULL); // array of normals  
396         glEnableClientState (GL_NORMAL_ARRAY);
397       }
398       if (myPArray->bufferVBO[VBOVtexels] != 0 && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
399       {
400         aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVtexels]);
401         glTexCoordPointer (2, GL_FLOAT, 0, NULL); // array of texture coordinates
402         glEnableClientState (GL_TEXTURE_COORD_ARRAY);
403       }
404       if (myPArray->bufferVBO[VBOVcolours] != 0)
405       {
406         aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVcolours]);
407         glColorPointer (4, GL_UNSIGNED_BYTE, 0, NULL); // array of colors 
408         glEnableClientState (GL_COLOR_ARRAY);
409         glColorMaterial (GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
410         glEnable (GL_COLOR_MATERIAL);
411       }
412     }
413
414     // OCC22236 NOTE: draw for all situations:
415     // 1) draw elements from myPArray->bufferVBO[VBOEdges] indicies array
416     // 2) draw elements from vertice array, when bounds defines count of primitive's verts.
417     // 3) draw primitive by vertexes if no edges and bounds array is specified
418     if (myPArray->flagBufferVBO == VBO_OK)
419     {
420       if (myPArray->num_edges > 0 && myPArray->bufferVBO[VBOEdges] != 0)
421       {
422         aGlContext->arbVBO->glBindBufferARB (GL_ELEMENT_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOEdges]); // for edge indices
423         if (myPArray->num_bounds > 0)
424         {
425           // draw primitives by vertex count with the indicies
426           Tint* anOffset = NULL;
427           for (i = 0; i < myPArray->num_bounds; ++i)
428           {
429             glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, anOffset);
430             anOffset += myPArray->bounds[i]; 
431           }
432         }
433         else
434         {
435           // draw one (or sequential) primitive by the indicies
436           glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, NULL);
437         }
438       }
439       else if (myPArray->num_bounds > 0)
440       {
441         for (i = n = 0; i < myPArray->num_bounds; ++i)
442         {
443           glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
444           n += myPArray->bounds[i];
445         }
446       }
447       else
448       {
449         glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
450       }
451
452       // bind with 0
453       aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0); 
454       aGlContext->arbVBO->glBindBufferARB (GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
455     } 
456     else
457     {
458       if (myPArray->num_bounds > 0)
459       {
460         if (myPArray->num_edges > 0)
461         {
462           for (i = n = 0; i < myPArray->num_bounds; ++i)
463           {
464             if (pfc != NULL) glColor3fv (pfc[i].rgb);
465             DrawElements (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
466                           myPArray->bounds[i], (GLenum* )&myPArray->edges[n]);
467             n += myPArray->bounds[i];
468           }
469         }
470         else
471         {
472           for (i = n = 0; i < myPArray->num_bounds; ++i)
473           {
474             if (pfc != NULL)
475             {
476               glColor3fv (pfc[i].rgb);
477             }
478             DrawArrays (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
479                         n, myPArray->bounds[i]);
480             n += myPArray->bounds[i];
481           }
482         }
483       }
484       else if (myPArray->num_edges > 0)
485       {
486         DrawElements (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
487                       myPArray->num_edges, (GLenum* )myPArray->edges);
488       }
489       else
490       {
491         DrawArrays (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
492                     0, myPArray->num_vertexs);
493       }
494     }
495
496     if (myPArray->bufferVBO[VBOVcolours] != 0 || pvc != NULL)
497     {
498       glDisable (GL_COLOR_MATERIAL);
499       theWorkspace->NamedStatus |= OPENGL_NS_RESMAT; // Reset material
500     }
501
502     if (myPArray->bufferVBO[VBOVertices] != 0 || myPArray->vertices != NULL)
503       glDisableClientState (GL_VERTEX_ARRAY);
504     if (myPArray->bufferVBO[VBOVcolours] != 0 || myPArray->vcolours != NULL)
505       glDisableClientState (GL_COLOR_ARRAY);
506     if (myPArray->bufferVBO[VBOVnormals] != 0 || myPArray->vnormals != NULL)
507       glDisableClientState (GL_NORMAL_ARRAY);
508     if ((myPArray->bufferVBO[VBOVtexels] != 0 && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0) || myPArray->vtexels != NULL)
509       glDisableClientState (GL_TEXTURE_COORD_ARRAY);
510
511     if (theWorkspace->DegenerateModel)
512     {
513       if (myDrawMode <= GL_LINE_STRIP)
514       {
515         glPopAttrib();
516       }
517       return;
518     }
519   }
520
521   if (theEdgeFlag || theWorkspace->DegenerateModel)
522   {
523     switch (theWorkspace->DegenerateModel)
524     {
525       default: // XXX_TDM_NODE or TINY
526         //  On some NVIDIA graphic cards, using glEdgeFlagPointer() in 
527         //  combination with VBO ( edge flag data put into a VBO buffer)
528         //  leads to a crash in a driver. Therefore, edge flags are simply 
529         //  igonored when VBOs are enabled, so all the edges are drawn if 
530         //  edge visibility is turned on. In order to draw edges selectively, 
531         //  either disable VBO or turn off edge visibilty in the current 
532         //  primitive array and create a separate primitive array (segments) 
533         //  and put edges to be drawn into it.
534         DrawEdges (theEdgeFlag ? theEdgeColour : theInteriorColour, theWorkspace);
535         break;
536       // DegenerateModel(as Lines, Points, BBoxs) are used only without VBO
537       case 2: // XXX_TDM_WIREFRAME
538         if (myPArray->VBOEnabled == 0)
539           DrawDegeneratesAsLines ((theEdgeFlag ? theEdgeColour : theInteriorColour), theWorkspace);
540         break;
541       case 3: // XXX_TDM_MARKER
542         if (myPArray->VBOEnabled == 0)
543           DrawDegeneratesAsPoints ((theEdgeFlag ? theEdgeColour : theInteriorColour), theWorkspace->SkipRatio);
544         break;
545       case 4: // XXX_TDM_BBOX
546         if (myPArray->VBOEnabled == 0)
547           DrawDegeneratesAsBBoxs (theEdgeFlag ? theEdgeColour : theInteriorColour);
548         break;
549     }
550   }
551
552   if (myDrawMode <= GL_LINE_STRIP)
553     glPopAttrib();
554 }
555
556 // =======================================================================
557 // function : DrawEdges
558 // purpose  :
559 // =======================================================================
560 void OpenGl_PrimitiveArray::DrawEdges (const TEL_COLOUR*               theEdgeColour,
561                                        const Handle(OpenGl_Workspace)& theWorkspace) const
562 {
563   glDisable (GL_LIGHTING);
564
565   const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
566   const OpenGl_AspectLine* anAspectLineOld = NULL;
567   if (myDrawMode > GL_LINE_STRIP)
568   {
569     anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge());
570     theWorkspace->AspectLine (Standard_True);
571
572     glPushAttrib (GL_POLYGON_BIT);
573     glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
574   }
575
576   Tint i, j, n;
577   GLint renderMode;
578
579   // OCC22236 NOTE: draw edges for all situations:
580   // 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indicies array
581   // 2) draw elements from vertice array, when bounds defines count of primitive's verts.
582   // 3) draw primitive's edges by vertexes if no edges and bounds array is specified
583   if (myPArray->flagBufferVBO == VBO_OK)
584   { 
585     aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVertices]);
586     glEnableClientState (GL_VERTEX_ARRAY);
587     glColor3fv (theEdgeColour->rgb);
588     if (myPArray->num_edges > 0 && myPArray->bufferVBO[VBOEdges])
589     {
590       aGlContext->arbVBO->glBindBufferARB (GL_ELEMENT_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOEdges]);
591
592       // draw primitives by vertex count with the indicies
593       if (myPArray->num_bounds > 0)
594       {
595         Tint* offset = 0;
596         for (i = 0, offset = 0; i < myPArray->num_bounds; ++i)
597         {
598           glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, offset);
599           offset += myPArray->bounds[i];
600         }
601       }
602       // draw one (or sequential) primitive by the indicies
603       else
604       {
605         glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, NULL);
606       }
607     }
608     else if (myPArray->num_bounds > 0)
609     {
610       for (i = n = 0; i < myPArray->num_bounds; ++i)
611       {
612         glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
613         n += myPArray->bounds[i];
614       }
615     }
616     else
617     {
618       glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
619     }
620
621     // unbind buffers
622     glDisableClientState (GL_VERTEX_ARRAY);
623     aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
624     aGlContext->arbVBO->glBindBufferARB (GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
625   }
626   else
627   {
628     glEnableClientState (GL_VERTEX_ARRAY);
629     glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices
630     glGetIntegerv (GL_RENDER_MODE, &renderMode);
631
632     glColor3fv (theEdgeColour->rgb);
633     if (myPArray->num_bounds > 0)
634     {
635       if (myPArray->num_edges > 0)
636       {
637         for (i = n = 0; i < myPArray->num_bounds; ++i)
638         {
639           if (myPArray->edge_vis)
640           {
641             glBegin (myDrawMode);
642             for (j = 0; j < myPArray->bounds[i]; ++j)
643             {
644               glEdgeFlag (myPArray->edge_vis[n+j]);
645               glVertex3fv (&myPArray->vertices[myPArray->edges[n+j]].xyz[0]);
646             }
647             glEnd();
648           }
649           else
650           {
651             DrawElements (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
652                           myPArray->bounds[i], (GLenum* )&myPArray->edges[n]);
653           }
654           n += myPArray->bounds[i];
655         }
656       }
657       else
658       {
659         for (i = n = 0 ; i < myPArray->num_bounds; ++i)
660         {
661           DrawArrays (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
662                       n, myPArray->bounds[i]);
663           n += myPArray->bounds[i];
664         }
665       }
666     } 
667     else if (myPArray->num_edges > 0)
668     {
669       if (myPArray->edge_vis)
670       {
671         glBegin (myDrawMode);
672         for (i = 0; i < myPArray->num_edges; ++i)
673         {
674           glEdgeFlag (myPArray->edge_vis[i]);
675           glVertex3fv (&myPArray->vertices[myPArray->edges[i]].xyz[0]);
676         }
677         glEnd();
678       }
679       else
680       {
681         DrawElements (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
682                       myPArray->num_edges, (GLenum* )myPArray->edges);
683       }
684     }
685     else
686     {
687       DrawArrays (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
688                   0, myPArray->num_vertexs);
689     }
690   }
691
692   if (myDrawMode > GL_LINE_STRIP)
693   {
694     // Restore line context
695     theWorkspace->SetAspectLine (anAspectLineOld);
696     glPopAttrib();
697   }
698 }
699
700 // =======================================================================
701 // function : DrawDegeneratesPointsAsPoints
702 // purpose  :
703 // =======================================================================
704 void OpenGl_PrimitiveArray::DrawDegeneratesPointsAsPoints() const
705
706   tel_point pv = myPArray->vertices;
707   for (Tint aVertId = 0; aVertId < myPArray->num_vertexs; ++aVertId)
708   {
709     glVertex3fv (&pv[aVertId].xyz[0]);
710   }
711 }
712
713 // =======================================================================
714 // function : DrawDegeneratesLinesAsPoints
715 // purpose  :
716 // =======================================================================
717 void OpenGl_PrimitiveArray::DrawDegeneratesLinesAsPoints() const
718 {
719   GLfloat pt[3];
720   tel_point pv = myPArray->vertices;
721
722   Tint j = 0;
723   while (j < myPArray->num_vertexs)
724   {
725     pt[0] = pv[j].xyz[0];
726     pt[1] = pv[j].xyz[1];
727     pt[2] = pv[j].xyz[2]; ++j;
728     pt[0] += pv[j].xyz[0];
729     pt[1] += pv[j].xyz[1];
730     pt[2] += pv[j].xyz[2]; ++j;
731     pt[0] *= 0.5f;
732     pt[1] *= 0.5f;
733     pt[2] *= 0.5f;
734     glVertex3fv (pt);
735   }
736 }  
737
738 // =======================================================================
739 // function : DrawDegeneratesTrianglesAsPoints
740 // purpose  :
741 // =======================================================================
742 void OpenGl_PrimitiveArray::DrawDegeneratesTrianglesAsPoints() const
743 {
744   Tint      i, j, iv;
745   GLfloat   pt[ 3 ];
746   tel_point pv = myPArray->vertices;
747
748   if (myPArray->num_edges > 0)
749   {
750     for (j = 0; j < myPArray->num_edges; j += 3)
751     {
752       iv = myPArray->edges[j];
753       pt[0] = pv[iv].xyz[0];
754       pt[1] = pv[iv].xyz[1];
755       pt[2] = pv[iv].xyz[2];
756       for (i = 1; i < 3; ++i)
757       {
758         iv = myPArray->edges[j+i];
759         pt[0] += pv[iv].xyz[0];
760         pt[1] += pv[iv].xyz[1];
761         pt[2] += pv[iv].xyz[2];
762       }
763       pt[0] /= 3.f;
764       pt[1] /= 3.f;
765       pt[2] /= 3.f;
766       glVertex3fv (pt);
767     }
768   }
769   else
770   {
771     for (j = 0; j < myPArray->num_vertexs; j += 3)
772     {
773       pt[0] = pv[j].xyz[0];
774       pt[1] = pv[j].xyz[1];
775       pt[2] = pv[j].xyz[2];
776       for (i = 1; i < 3; ++i)
777       {
778         pt[0] += pv[j+i].xyz[0];
779         pt[1] += pv[j+i].xyz[1];
780         pt[2] += pv[j+i].xyz[2];
781       }
782       pt[0] /= 3.f;
783       pt[1] /= 3.f;
784       pt[2] /= 3.f;
785       glVertex3fv (pt);
786     }
787   }
788 }
789
790 // =======================================================================
791 // function : DrawDegeneratesTrianglesAsPoints
792 // purpose  :
793 // =======================================================================
794 void OpenGl_PrimitiveArray::DrawDegeneratesTrianglestripsAsPoints() const
795
796   Tint      i, j, k, n;
797   GLfloat   pt[ 3 ];
798   tel_point pv = myPArray->vertices;
799
800   if (myPArray->num_bounds > 0)
801   {
802     for (k = n = 0; k < myPArray->num_bounds; ++k)
803     {
804       for (j = 0; j < myPArray->bounds[k] - 2; ++j)
805       {
806         pt[0] = pv[n+j].xyz[0];
807         pt[1] = pv[n+j].xyz[1];
808         pt[2] = pv[n+j].xyz[2];
809         for (i = 1; i < 3; ++i)
810         {
811           pt[0] += pv[n+j+i].xyz[0];
812           pt[1] += pv[n+j+i].xyz[1];
813           pt[2] += pv[n+j+i].xyz[2];
814         }
815         pt[0] /= 3.f;
816         pt[1] /= 3.f;
817         pt[2] /= 3.f;
818         glVertex3fv (pt);
819       }
820       n += myPArray->bounds[k];
821     }
822   }
823   else
824   {
825     for (j = 0; j < myPArray->num_vertexs - 2; ++j)
826     {
827       pt[0] = pv[j].xyz[0];
828       pt[1] = pv[j].xyz[1];
829       pt[2] = pv[j].xyz[2];
830       for (i = 1; i < 3; ++i)
831       {
832         pt[0] += pv[j+i].xyz[0];
833         pt[1] += pv[j+i].xyz[1];
834         pt[2] += pv[j+i].xyz[2];
835       }
836       pt[0] /= 3.f;
837       pt[1] /= 3.f;
838       pt[2] /= 3.f;
839       glVertex3fv (pt);
840     }
841   }
842 }
843
844 // =======================================================================
845 // function : DrawDegeneratesPolygonsAsPoints
846 // purpose  :
847 // =======================================================================
848 void OpenGl_PrimitiveArray::DrawDegeneratesPolygonsAsPoints() const
849
850   Tint      j, k, n, iv;
851   GLfloat   pt[3];
852   tel_point pv = myPArray->vertices;
853
854   if (myPArray->num_bounds > 0)
855   {
856     if (myPArray->num_edges > 0)
857     {
858       for (k = n = 0; k < myPArray->num_bounds; ++k)
859       {
860         pt[0] = pt[1] = pt[2] = 0.0;
861         for (j = 0; j < myPArray->bounds[k]; ++j)
862         {
863           iv = myPArray->edges[n+j];
864           pt[0] += pv[iv].xyz[0];
865           pt[1] += pv[iv].xyz[1];
866           pt[2] += pv[iv].xyz[2];
867         }
868         pt[0] /= myPArray->bounds[k];
869         pt[1] /= myPArray->bounds[k];
870         pt[2] /= myPArray->bounds[k];
871         glVertex3fv (pt);
872         n += myPArray->bounds[k];
873       }
874     }
875     else
876     {
877       for (k = n = 0; k < myPArray->num_bounds; ++k)
878       {
879         pt[0] = pt[1] = pt[2] = 0.0;
880         for (j = 0; j < myPArray->bounds[k]; ++j)
881         {
882           pt[0] += pv[n+j].xyz[0];
883           pt[1] += pv[n+j].xyz[1];
884           pt[2] += pv[n+j].xyz[2];
885         }
886         pt[0] /= myPArray->bounds[k];
887         pt[1] /= myPArray->bounds[k];
888         pt[2] /= myPArray->bounds[k];
889         glVertex3fv (pt);
890         n += myPArray->bounds[k];
891       }
892     }
893   }
894   else if (myPArray->num_edges > 0)
895   {
896     pt[0] = pt[1] = pt[2] = 0.0;
897     for (j = 0; j < myPArray->num_edges; ++j)
898     {
899       iv = myPArray->edges[j];
900       pt[0] += pv[iv].xyz[0];
901       pt[1] += pv[iv].xyz[1];
902       pt[2] += pv[iv].xyz[2];
903     }
904     pt[0] /= myPArray->num_edges;
905     pt[1] /= myPArray->num_edges;
906     pt[2] /= myPArray->num_edges;
907     glVertex3fv (pt);
908   }
909   else
910   {
911     pt[0] = pt[1] = pt[2] = 0.0;
912     for (j = 0; j < myPArray->num_vertexs; ++j)
913     {
914       pt[0] += pv[j].xyz[0];
915       pt[1] += pv[j].xyz[1];
916       pt[2] += pv[j].xyz[2];
917     }
918     pt[0] /= myPArray->num_vertexs;
919     pt[1] /= myPArray->num_vertexs;
920     pt[2] /= myPArray->num_vertexs;
921     glVertex3fv (pt);
922   }
923 }
924
925 // =======================================================================
926 // function : DrawDegeneratesQuadranglesAsPoints
927 // purpose  :
928 // =======================================================================
929 void OpenGl_PrimitiveArray::DrawDegeneratesQuadranglesAsPoints() const
930 {
931   Tint      i, j, iv;
932   GLfloat   pt[ 3 ];
933   tel_point pv = myPArray->vertices;
934
935   if (myPArray->num_edges > 0)
936   {
937     for (j = 0; j < myPArray->num_edges; j += 4)
938     {
939       pt[0] = pt[1] = pt[2] = 0.0;
940       for (i = 0; i < 4; ++i)
941       {
942         iv = myPArray->edges[j+i];
943         pt[0] += pv[iv].xyz[0];
944         pt[1] += pv[iv].xyz[1];
945         pt[2] += pv[iv].xyz[2];
946       }
947       pt[0] /= 4;
948       pt[1] /= 4;
949       pt[2] /= 4;
950       glVertex3fv ( pt );
951     }
952   }
953   else
954   {
955     for (j = 0; j < myPArray->num_vertexs; j += 4)
956     {
957       pt[0] = pt[1] = pt[2] = 0.0;
958       for (i = 0; i < 4; ++i)
959       {
960         pt[0] += pv[j+i].xyz[0];
961         pt[1] += pv[j+i].xyz[1];
962         pt[2] += pv[j+i].xyz[2];
963       }
964       pt[0] /= 4;
965       pt[1] /= 4;
966       pt[2] /= 4;
967       glVertex3fv (pt);
968     }
969   }
970 }  
971
972 // =======================================================================
973 // function : DrawDegeneratesAsPoints
974 // purpose  :
975 // =======================================================================
976 void OpenGl_PrimitiveArray::DrawDegeneratesQuadranglestripsAsPoints() const
977
978   Tint      i, j, k, n;
979   GLfloat   pt[3];
980   tel_point pv = myPArray->vertices;
981
982   if (myPArray->num_bounds > 0)
983   {
984     for (k = n = 0; k < myPArray->num_bounds; ++k)
985     {
986       for (j = 0; j < myPArray->bounds[k] - 2; j += 2)
987       {
988         pt[0] = pt[1] = pt[2] = 0.;
989         for (i = 0; i < 4; ++i)
990         {
991           pt[0] += pv[n+j+i].xyz[0];
992           pt[1] += pv[n+j+i].xyz[1];
993           pt[2] += pv[n+j+i].xyz[2];
994         }
995         pt[0] /= 4;
996         pt[1] /= 4;
997         pt[2] /= 4;
998         glVertex3fv (pt);
999       }
1000       n += myPArray->bounds[k];
1001     }
1002   }
1003   else
1004   {
1005     for (j = 0; j < myPArray->num_vertexs - 2; j += 2)
1006     {
1007       pt[0] = pt[1] = pt[2] = 0.;
1008       for (i = 0; i < 4; ++i)
1009       {
1010         pt[0] += pv[j+i].xyz[0];
1011         pt[1] += pv[j+i].xyz[1];
1012         pt[2] += pv[j+i].xyz[2];
1013       }
1014       pt[0] /= 4;
1015       pt[1] /= 4;
1016       pt[2] /= 4;
1017       glVertex3fv (pt);
1018     }
1019   }
1020 }
1021
1022 // =======================================================================
1023 // function : DrawDegeneratesAsPoints
1024 // purpose  :
1025 // =======================================================================
1026 void OpenGl_PrimitiveArray::DrawDegeneratesAsPoints (const TEL_COLOUR* theEdgeColour,
1027                                                      const float       theSkipRatio) const
1028 {
1029   if (theSkipRatio >= 1.0f)
1030     return;
1031
1032   GLboolean zbuff_state = glIsEnabled (GL_DEPTH_TEST);
1033   glDisable (GL_LIGHTING);
1034   if (zbuff_state)
1035     glDisable (GL_DEPTH_TEST); 
1036   glColor3fv (theEdgeColour->rgb);
1037
1038   glBegin (GL_POINTS);
1039   switch (myDrawMode)
1040   {
1041     case GL_POINTS:
1042       DrawDegeneratesPointsAsPoints();
1043       break;
1044     case GL_LINES:
1045       DrawDegeneratesLinesAsPoints();
1046       break;
1047     case GL_LINE_STRIP:
1048     case GL_POLYGON:
1049       DrawDegeneratesPolygonsAsPoints();
1050       break;
1051     case GL_TRIANGLES:
1052       DrawDegeneratesTrianglesAsPoints();
1053       break;
1054     case GL_QUADS:
1055       DrawDegeneratesQuadranglesAsPoints();
1056       break;
1057     case GL_TRIANGLE_FAN:
1058     case GL_TRIANGLE_STRIP:
1059       DrawDegeneratesTrianglestripsAsPoints();
1060       break;
1061     case GL_QUAD_STRIP:
1062       DrawDegeneratesQuadranglestripsAsPoints();
1063       break;
1064     default:
1065       break;
1066   }
1067   glEnd();
1068   if (zbuff_state)
1069     glEnable (GL_DEPTH_TEST);
1070 }
1071
1072 // =======================================================================
1073 // function : DrawDegeneratesLinesAsLines
1074 // purpose  :
1075 // =======================================================================
1076 void OpenGl_PrimitiveArray::DrawDegeneratesLinesAsLines (const float theSkipRatio) const
1077 {
1078   Tint i, iv;
1079   tel_point  pv = myPArray->vertices;
1080
1081   Tint n = myPArray->num_vertexs;
1082   Tint j = int((1.0f - theSkipRatio) * n);
1083   for (; j > 0; --j)
1084   {
1085     i = OGL_Rand() % n;
1086     myPArray->keys[i] = -myPArray->keys[i];
1087   }
1088
1089   if (myPArray->num_bounds > 0)
1090   {
1091     if (myPArray->num_edges > 0)
1092     {
1093       for (i = n = 0; i < myPArray->num_bounds; ++i)
1094       {
1095         glBegin (GL_LINES);
1096         for (j = 0; j < myPArray->bounds[i]; ++j)
1097         {
1098           iv = myPArray->edges[n + j];
1099           if (myPArray->keys[iv] < 0)
1100           {
1101             myPArray->keys[iv] = -myPArray->keys[iv];
1102             glVertex3fv (pv[iv].xyz);
1103           }
1104         }
1105         glEnd();
1106         n += myPArray->bounds[i];
1107       }
1108     }
1109     else
1110     {
1111       for (i = n = 0; i < myPArray->num_bounds; ++i)
1112       {
1113         glBegin (GL_LINES);
1114         for (j = 0; j < myPArray->bounds[i]; ++j)
1115         {
1116           if (myPArray->keys[n+j] < 0)
1117           {
1118             myPArray->keys[n+j] = -myPArray->keys[n+j];
1119             glVertex3fv (pv[n+j].xyz);
1120           }
1121         }
1122         glEnd();
1123         n += myPArray->bounds[i];
1124       }
1125     }
1126   }
1127   else if (myPArray->num_edges > 0)
1128   {
1129     glBegin (GL_LINES);
1130     for (j = 0; j < myPArray->num_edges; ++j)
1131     {
1132       iv = myPArray->edges[j];
1133       if (myPArray->keys[iv] < 0)
1134       {
1135         myPArray->keys[iv] = -myPArray->keys[iv];
1136         glVertex3fv (pv[iv].xyz);
1137       }
1138     }
1139     glEnd();
1140   }
1141   else
1142   {
1143     glBegin (GL_LINES);
1144     for (j = 0; j < myPArray->num_vertexs; ++j)
1145     {
1146       if (myPArray->keys[j] < 0)
1147       {
1148         myPArray->keys[j] = -myPArray->keys[j];
1149         glVertex3fv (pv[j].xyz);
1150       }
1151     }
1152     glEnd();
1153   }
1154 }
1155
1156 // =======================================================================
1157 // function : DrawDegeneratesTrianglesAsLines
1158 // purpose  :
1159 // =======================================================================
1160 void OpenGl_PrimitiveArray::DrawDegeneratesTrianglesAsLines (const float theSkipRatio) const
1161
1162   Tint i, iv;
1163   tel_point pv = myPArray->vertices;
1164
1165   Tint n = myPArray->num_vertexs / 3;
1166   Tint j = int((1.0f - theSkipRatio) * n);
1167   for (; j > 0; --j)
1168   {
1169     i = OGL_Rand() % n; i *= 3;
1170     myPArray->keys[i] = -myPArray->keys[i];
1171   }
1172
1173   if (myPArray->num_edges > 0)
1174   {
1175     for (j = 0; j < myPArray->num_edges; j += 3)
1176     {
1177       iv = myPArray->edges[j];
1178       if (myPArray->keys[iv] < 0)
1179       { 
1180         myPArray->keys[iv] = -myPArray->keys[iv];
1181         glBegin (GL_LINE_LOOP);
1182         for (i = 0; i < 3; ++i)
1183         {
1184           iv = myPArray->edges[j+i];
1185           glVertex3fv (pv[iv].xyz);
1186         }
1187         glEnd();
1188       }
1189     }
1190   }
1191   else
1192   {
1193     for (j = 0; j < myPArray->num_vertexs; j += 3)
1194     {
1195       if (myPArray->keys[j] < 0)
1196       {
1197         myPArray->keys[j] = -myPArray->keys[j];
1198         glBegin (GL_LINE_LOOP);
1199         for (i = 0; i < 3; ++i)
1200         {
1201           glVertex3fv (pv[j+i].xyz);
1202         }
1203         glEnd();
1204       }
1205     }
1206   }
1207 }
1208
1209 // =======================================================================
1210 // function : DrawDegeneratesTrianglesAsLines
1211 // purpose  :
1212 // =======================================================================
1213 void OpenGl_PrimitiveArray::DrawDegeneratesTrianglestripsAsLines (const float theSkipRatio) const
1214
1215   Tint i, j, k, n, ni;
1216   tel_point pv = myPArray->vertices;
1217
1218   if (myPArray->num_bounds > 0)
1219   {
1220     for (i = n = 0; i < myPArray->num_bounds; ++i)
1221     {
1222       ni = myPArray->bounds[i] - 2;
1223       k = int((1.0f - theSkipRatio) * ni);
1224       for (; k > 0; --k)
1225       {
1226         j = OGL_Rand() % ni; j += 2;
1227         myPArray->keys[n+j] = -myPArray->keys[n+j];
1228       }
1229       for (j = 2; j < myPArray->bounds[i]; ++j)
1230       {
1231         if (myPArray->keys[n+j] < 0)
1232         {
1233           myPArray->keys[n+j] = -myPArray->keys[n+j];
1234           glBegin (GL_LINE_LOOP);
1235           glVertex3fv (pv[n+j-2].xyz);
1236           glVertex3fv (pv[n+j-1].xyz);
1237           glVertex3fv (pv[n+j].xyz);
1238           glEnd();
1239         }
1240       }
1241       n += myPArray->bounds[i];
1242     }
1243   }
1244   else
1245   {
1246     ni = myPArray->num_vertexs - 2;
1247     k = int((1.0f - theSkipRatio) * ni);
1248     for (; k > 0; --k)
1249     {
1250       j = OGL_Rand() % ni; j += 2;
1251       myPArray->keys[j] = -myPArray->keys[j];
1252     }
1253     for (j = 2; j < myPArray->num_vertexs; ++j)
1254     {
1255       if (myPArray->keys[j] < 0)
1256       {
1257         myPArray->keys[j] = -myPArray->keys[j];
1258         glBegin (GL_LINE_LOOP);
1259         glVertex3fv (pv[j-2].xyz);
1260         glVertex3fv (pv[j-1].xyz);
1261         glVertex3fv (pv[j].xyz);
1262         glEnd();
1263       }
1264     }
1265   }
1266 }
1267
1268 // =======================================================================
1269 // function : DrawDegeneratesPolygonsAsLines
1270 // purpose  :
1271 // =======================================================================
1272 void OpenGl_PrimitiveArray::DrawDegeneratesPolygonsAsLines (const float theSkipRatio) const
1273
1274   Tint i, iv;
1275   tel_point pv = myPArray->vertices;
1276
1277   Tint n = myPArray->num_vertexs;
1278   Tint j = int((1.0f - theSkipRatio) * n);
1279   for (; j > 0; --j)
1280   {
1281     i = OGL_Rand() % n;
1282     myPArray->keys[i] = -myPArray->keys[i];
1283   }
1284
1285   if (myPArray->num_bounds > 0)
1286   {
1287     if (myPArray->num_edges > 0)
1288     {
1289       for (i = n = 0; i < myPArray->num_bounds; ++i)
1290       {
1291         glBegin (GL_LINE_LOOP);
1292         for (j = 0; j < myPArray->bounds[i]; ++j)
1293         {
1294           iv = myPArray->edges[n+j];
1295           if (myPArray->keys[iv] < 0)
1296           {
1297             myPArray->keys[iv] = -myPArray->keys[iv];
1298             glVertex3fv (pv[iv].xyz);
1299           }
1300         }
1301         glEnd();
1302         n += myPArray->bounds[i];
1303       }
1304     }
1305     else
1306     {
1307       for (i = n = 0; i < myPArray->num_bounds; ++i)
1308       {
1309         glBegin (GL_LINE_LOOP);
1310         for (j = 0; j < myPArray->bounds[i]; ++j)
1311         {
1312           if (myPArray->keys[n+j] < 0)
1313           {
1314             myPArray->keys[n+j] = -myPArray->keys[n+j];
1315             glVertex3fv (pv[n+j].xyz);
1316           }
1317         }
1318         glEnd();
1319         n += myPArray->bounds[i];
1320       }
1321     }
1322   }
1323   else if (myPArray->num_edges > 0)
1324   {
1325     glBegin (GL_LINE_LOOP);
1326     for (j = 0; j < myPArray->num_edges; ++j)
1327     {
1328       iv = myPArray->edges[j];
1329       if (myPArray->keys[iv] < 0)
1330       {
1331         myPArray->keys[iv] = -myPArray->keys[iv];
1332         glVertex3fv (pv[iv].xyz);
1333       }
1334     }
1335     glEnd();
1336   }
1337   else
1338   {
1339     glBegin (GL_LINE_LOOP);
1340     for (j = 0; j < myPArray->num_vertexs; ++j)
1341     {
1342       if (myPArray->keys[j] < 0)
1343       {
1344         myPArray->keys[j] = -myPArray->keys[j];
1345         glVertex3fv (pv[j].xyz);
1346       }
1347     }
1348     glEnd();
1349   }
1350 }  
1351
1352 // =======================================================================
1353 // function : DrawDegeneratesQuadranglesAsLines
1354 // purpose  :
1355 // =======================================================================
1356 void OpenGl_PrimitiveArray::DrawDegeneratesQuadranglesAsLines (const float theSkipRatio) const
1357 {
1358   Tint i, iv;
1359   tel_point pv = myPArray->vertices;
1360
1361   Tint n = myPArray->num_vertexs / 4;
1362   Tint j = int((1.0f - theSkipRatio) * n);
1363   for (; j > 0; --j)
1364   {
1365     i = OGL_Rand() % n; i *= 4;
1366     myPArray->keys[i] = -myPArray->keys[i];
1367   }
1368
1369   if (myPArray->num_edges > 0)
1370   {
1371     for (j = 0; j < myPArray->num_edges; j += 4)
1372     {
1373       iv = myPArray->edges[j];
1374       if (myPArray->keys[iv] < 0)
1375       {
1376         myPArray->keys[iv] = -myPArray->keys[iv];
1377         glBegin (GL_LINE_LOOP);
1378         for (i = 0; i < 4; ++i)
1379         {
1380           iv = myPArray->edges[j+i];
1381           glVertex3fv (pv[iv].xyz);
1382         }
1383         glEnd();
1384       }
1385     }
1386   }
1387   else
1388   {
1389     for (j = 0; j < myPArray->num_vertexs; j += 4)
1390     {
1391       if (myPArray->keys[j] < 0)
1392       {
1393         myPArray->keys[j] = -myPArray->keys[j];
1394         glBegin (GL_LINE_LOOP);
1395         for (i = 0; i < 4; ++i)
1396         {
1397           glVertex3fv (pv[j+i].xyz);
1398         }
1399         glEnd();
1400       }
1401     }
1402   }
1403 }
1404
1405 // =======================================================================
1406 // function : DrawDegeneratesQuadranglesAsLines
1407 // purpose  :
1408 // =======================================================================
1409 void OpenGl_PrimitiveArray::DrawDegeneratesQuadranglestripsAsLines (const float theSkipRatio) const
1410
1411   Tint i, j, k, n, ni;
1412   tel_point pv = myPArray->vertices;
1413
1414   if (myPArray->num_bounds > 0)
1415   {
1416     for (i = n = 0; i < myPArray->num_bounds; ++i)
1417     {
1418       ni = myPArray->bounds[i] / 2 - 2;
1419       k = int((1.0f - theSkipRatio) * ni);
1420       for (; k > 0; --k)
1421       {
1422         j = OGL_Rand() % ni; j = j * 2 + 2;
1423         myPArray->keys[n+j] = -myPArray->keys[n+j];
1424       }
1425       for (j = 3; j < myPArray->bounds[i]; j += 2)
1426       {
1427         if (myPArray->keys[n+j] < 0)
1428         {
1429           myPArray->keys[n+j] = -myPArray->keys[n+j];
1430           glBegin (GL_LINE_LOOP);
1431           glVertex3fv (pv[n+j-3].xyz);
1432           glVertex3fv (pv[n+j-2].xyz);
1433           glVertex3fv (pv[n+j-1].xyz);
1434           glVertex3fv (pv[n+j].xyz);
1435           glEnd();
1436         }
1437       }
1438       n += myPArray->bounds[i];
1439     }
1440   }
1441   else
1442   {
1443     ni = myPArray->num_vertexs / 2 - 2;
1444     k = int((1.0f - theSkipRatio) * ni);
1445     for (; k > 0; --k)
1446     {
1447       j = OGL_Rand() % ni; j = j * 2 + 2;
1448       myPArray->keys[j] = -myPArray->keys[j];
1449     }
1450     for (j = 3; j < myPArray->num_vertexs; j += 2)
1451     {
1452       if (myPArray->keys[j] < 0)
1453       {
1454         myPArray->keys[j] = -myPArray->keys[j];
1455         glBegin (GL_LINE_LOOP);
1456         glVertex3fv (pv[j-3].xyz);
1457         glVertex3fv (pv[j-2].xyz);
1458         glVertex3fv (pv[j-1].xyz);
1459         glVertex3fv (pv[j].xyz);
1460         glEnd();
1461       }
1462     }
1463   }
1464 }
1465
1466 // =======================================================================
1467 // function : DrawDegeneratesAsLines
1468 // purpose  :
1469 // =======================================================================
1470 void OpenGl_PrimitiveArray::DrawDegeneratesAsLines (const TEL_COLOUR*               theEdgeColour,
1471                                                     const Handle(OpenGl_Workspace)& theWorkspace) const
1472 {
1473   const float aSkipRatio = theWorkspace->SkipRatio;
1474
1475   GLboolean zbuff_state = glIsEnabled (GL_DEPTH_TEST);
1476
1477   glDisable (GL_LIGHTING);
1478
1479   if (zbuff_state)
1480     glDisable (GL_DEPTH_TEST); 
1481
1482   glColor3fv (theEdgeColour->rgb);
1483
1484   if (aSkipRatio != 0.0f)
1485   {
1486     switch (myDrawMode)
1487     {
1488       case GL_POINTS:
1489         if (aSkipRatio < 1.0f)
1490           DrawDegeneratesPointsAsPoints();
1491         break;
1492       case GL_LINES:
1493         DrawDegeneratesLinesAsLines (aSkipRatio);
1494         break;
1495       case GL_LINE_STRIP:
1496       case GL_POLYGON:
1497         DrawDegeneratesPolygonsAsLines (aSkipRatio);
1498         break;
1499       case GL_TRIANGLES:
1500         DrawDegeneratesTrianglesAsLines (aSkipRatio);
1501         break;
1502       case GL_QUADS:
1503         DrawDegeneratesQuadranglesAsLines (aSkipRatio);
1504         break;
1505       case GL_TRIANGLE_FAN:
1506       case GL_TRIANGLE_STRIP:
1507         DrawDegeneratesTrianglestripsAsLines (aSkipRatio);
1508         break;
1509       case GL_QUAD_STRIP:
1510         DrawDegeneratesQuadranglestripsAsLines (aSkipRatio);
1511         break;
1512       default:
1513         break;
1514     }
1515   }
1516   else
1517   {
1518     int i,n;
1519     glPushAttrib (GL_POLYGON_BIT);
1520     glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
1521
1522     GLboolean color_array_mode         = glIsEnabled (GL_COLOR_ARRAY);
1523     GLboolean edge_flag_array_mode     = glIsEnabled (GL_EDGE_FLAG_ARRAY);
1524     GLboolean index_array_mode         = glIsEnabled (GL_INDEX_ARRAY);
1525     GLboolean normal_array_mode        = glIsEnabled (GL_NORMAL_ARRAY);
1526     GLboolean texture_coord_array_mode = glIsEnabled (GL_TEXTURE_COORD_ARRAY);
1527     GLboolean vertex_array_mode        = glIsEnabled (GL_VERTEX_ARRAY);
1528
1529     glDisableClientState (GL_COLOR_ARRAY);
1530     glDisableClientState (GL_EDGE_FLAG_ARRAY);
1531     glDisableClientState (GL_INDEX_ARRAY);
1532     glDisableClientState (GL_NORMAL_ARRAY);
1533     glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1534
1535     if (!vertex_array_mode)
1536       glEnableClientState (GL_VERTEX_ARRAY);
1537
1538     glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices
1539
1540     GLint renderMode;
1541     glGetIntegerv (GL_RENDER_MODE, &renderMode);
1542
1543     if (myPArray->num_bounds > 0)
1544     {
1545       if (myPArray->num_edges > 0)
1546       {
1547         for (i = n = 0; i < myPArray->num_bounds; ++i)
1548         {
1549           DrawElements (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
1550                         myPArray->bounds[i], (GLenum* )&myPArray->edges[n]);
1551           n += myPArray->bounds[i];
1552         }
1553       }
1554       else
1555       {
1556         for (i = n = 0; i < myPArray->num_bounds; ++i)
1557         {
1558           DrawArrays (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
1559                       n, myPArray->bounds[i]);
1560           n += myPArray->bounds[i];
1561         }
1562       }
1563     }
1564     else if (myPArray->num_edges > 0)
1565     {
1566       DrawElements (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
1567                     myPArray->num_edges, (GLenum* )myPArray->edges);
1568     }
1569     else
1570     {
1571       DrawArrays (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
1572                   0, myPArray->num_vertexs);
1573     }
1574
1575     if (!vertex_array_mode) glDisableClientState (GL_VERTEX_ARRAY);
1576
1577     if (color_array_mode)         glEnableClientState (GL_COLOR_ARRAY);
1578     if (edge_flag_array_mode)     glEnableClientState (GL_EDGE_FLAG_ARRAY);
1579     if (index_array_mode)         glEnableClientState (GL_INDEX_ARRAY);
1580     if (normal_array_mode)        glEnableClientState (GL_NORMAL_ARRAY);
1581     if (texture_coord_array_mode) glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1582
1583     glPopAttrib();
1584   }
1585
1586   if (zbuff_state)
1587     glEnable(GL_DEPTH_TEST); 
1588 }  
1589
1590 // =======================================================================
1591 // function : DrawDegeneratesAsBBoxs
1592 // purpose  :
1593 // =======================================================================
1594 void OpenGl_PrimitiveArray::DrawDegeneratesAsBBoxs (const TEL_COLOUR* theEdgeColour) const
1595 {
1596   GLfloat minp[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
1597   GLfloat maxp[3] = { FLT_MIN, FLT_MIN, FLT_MIN };
1598   tel_point pv = myPArray->vertices;
1599
1600   glDisable (GL_LIGHTING);
1601
1602   glColor3fv (theEdgeColour->rgb);
1603
1604   for (Tint i = 0; i < myPArray->num_vertexs; ++i)
1605   {
1606     if (pv[i].xyz[0] < minp[0])
1607       minp[0] = pv[i].xyz[0];
1608     if (pv[i].xyz[1] < minp[1])
1609       minp[1] = pv[i].xyz[1];
1610     if (pv[i].xyz[2] < minp[2])
1611       minp[2] = pv[i].xyz[2];
1612
1613     if (pv[i].xyz[0] > maxp[0])
1614       maxp[0] = pv[i].xyz[0];
1615     if (pv[i].xyz[1] > maxp[1])
1616       maxp[1] = pv[i].xyz[1];
1617     if (pv[i].xyz[2] > maxp[2])
1618       maxp[2] = pv[i].xyz[2];
1619   }
1620
1621   glBegin (GL_LINE_STRIP);
1622
1623   glVertex3fv (minp);
1624   glVertex3f (minp[0], maxp[1], minp[2]);
1625   glVertex3f (minp[0], maxp[1], maxp[2]);
1626   glVertex3f (minp[0], minp[1], maxp[2]);
1627   glVertex3f (minp[0], minp[1], minp[2]);
1628
1629   glVertex3f (maxp[0], minp[1], minp[2]);
1630   glVertex3f (maxp[0], maxp[1], minp[2]);
1631   glVertex3f (maxp[0], maxp[1], maxp[2]);
1632   glVertex3f (maxp[0], minp[1], maxp[2]);
1633   glVertex3f (maxp[0], minp[1], minp[2]);
1634
1635   glVertex3f (maxp[0], minp[1], maxp[2]);
1636   glVertex3f (minp[0], minp[1], maxp[2]);
1637   glVertex3f (minp[0], maxp[1], maxp[2]);
1638   glVertex3fv (maxp);
1639   glVertex3f (maxp[0], maxp[1], minp[2]);
1640   glVertex3f (minp[0], maxp[1], minp[2]);
1641
1642   glEnd();
1643 }
1644
1645 // =======================================================================
1646 // function : OpenGl_PrimitiveArray
1647 // purpose  :
1648 // =======================================================================
1649 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (CALL_DEF_PARRAY* thePArray)
1650 : myPArray (thePArray),
1651   myDrawMode (GL_NONE)
1652 {
1653   switch (myPArray->type)
1654   {
1655     case TelPointsArrayType:
1656       myDrawMode = GL_POINTS;
1657       break;
1658     case TelPolylinesArrayType:
1659       myDrawMode = GL_LINE_STRIP;
1660       break;
1661     case TelSegmentsArrayType:
1662       myDrawMode = GL_LINES;
1663       break;
1664     case TelPolygonsArrayType:
1665       myDrawMode = GL_POLYGON;
1666       break;
1667     case TelTrianglesArrayType:
1668       myDrawMode = GL_TRIANGLES;
1669       break;
1670     case TelQuadranglesArrayType:
1671       myDrawMode = GL_QUADS;
1672       break;
1673     case TelTriangleStripsArrayType:
1674       myDrawMode = GL_TRIANGLE_STRIP;
1675       break;
1676     case TelQuadrangleStripsArrayType:
1677       myDrawMode = GL_QUAD_STRIP;
1678       break;
1679     case TelTriangleFansArrayType:
1680       myDrawMode = GL_TRIANGLE_FAN;
1681       break;
1682   }
1683 }
1684
1685 // =======================================================================
1686 // function : ~OpenGl_PrimitiveArray
1687 // purpose  :
1688 // =======================================================================
1689 OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray ()
1690 {
1691   if (myPArray == NULL)
1692     return;
1693
1694   if (myPArray->VBOEnabled == VBO_OK)
1695   {
1696     OpenGl_ResourceCleaner* aResCleaner = OpenGl_ResourceCleaner::GetInstance();
1697     if (myPArray->bufferVBO[VBOEdges] != 0)
1698       aResCleaner->AddResource ((GLCONTEXT )myPArray->contextId,
1699                                 new OpenGl_ResourceVBO (myPArray->bufferVBO[VBOEdges]));
1700     if (myPArray->bufferVBO[VBOVertices] != 0)
1701       aResCleaner->AddResource ((GLCONTEXT )myPArray->contextId,
1702                                 new OpenGl_ResourceVBO (myPArray->bufferVBO[VBOVertices]));
1703     if (myPArray->bufferVBO[VBOVcolours] != 0)
1704       aResCleaner->AddResource ((GLCONTEXT )myPArray->contextId,
1705                                 new OpenGl_ResourceVBO (myPArray->bufferVBO[VBOVcolours]));
1706     if (myPArray->bufferVBO[VBOVnormals] != 0)
1707       aResCleaner->AddResource ((GLCONTEXT )myPArray->contextId,
1708                                 new OpenGl_ResourceVBO (myPArray->bufferVBO[VBOVnormals]));
1709     if (myPArray->bufferVBO[VBOVtexels] != 0)
1710       aResCleaner->AddResource ((GLCONTEXT )myPArray->contextId,
1711                                 new OpenGl_ResourceVBO (myPArray->bufferVBO[VBOVtexels]));
1712   }
1713 }
1714
1715 // =======================================================================
1716 // function : Render
1717 // purpose  :
1718 // =======================================================================
1719 void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
1720 {
1721   if (myPArray == NULL || myDrawMode == GL_NONE)
1722     return;
1723
1724   // create VBOs on first render call
1725   if (myPArray->VBOEnabled == -1) // special value for uninitialized state
1726   {
1727     myPArray->VBOEnabled = OpenGl_GraphicDriver::ToUseVBO() && (theWorkspace->GetGlContext()->arbVBO != NULL);
1728     if (myPArray->VBOEnabled != 0)
1729       BuildVBO (theWorkspace);
1730   }
1731
1732   switch (myPArray->type)
1733   {
1734     case TelPointsArrayType:
1735     case TelPolylinesArrayType:
1736     case TelSegmentsArrayType:
1737     {
1738       glDisable (GL_LIGHTING);
1739
1740       if ((theWorkspace->NamedStatus & OPENGL_NS_ANIMATION) != 0 &&
1741           (theWorkspace->NamedStatus & OPENGL_NS_WIREFRAME) == 0 &&
1742            theWorkspace->DegenerateModel)
1743       {
1744         glDisable (GL_DEPTH_TEST);
1745         if (theWorkspace->NamedStatus & OPENGL_NS_TEXTURE)
1746           DisableTexture();
1747         theWorkspace->NamedStatus |= OPENGL_NS_WIREFRAME;
1748       }
1749       break;
1750     }
1751     case TelPolygonsArrayType:
1752     case TelTrianglesArrayType:
1753     case TelQuadranglesArrayType:
1754     case TelTriangleStripsArrayType:
1755     case TelTriangleFansArrayType:
1756     case TelQuadrangleStripsArrayType:
1757     {
1758       if ((theWorkspace->NamedStatus & OPENGL_NS_ANIMATION) != 0 &&
1759           (theWorkspace->NamedStatus & OPENGL_NS_WIREFRAME) != 0 &&
1760            theWorkspace->DegenerateModel < 2)
1761       {
1762         if (theWorkspace->NamedStatus & OPENGL_NS_TEXTURE)
1763           EnableTexture();
1764         glEnable (GL_DEPTH_TEST);
1765         theWorkspace->NamedStatus &= ~OPENGL_NS_WIREFRAME;
1766       }
1767       break;
1768     }
1769     default:
1770       break;
1771   }
1772
1773   const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace (Standard_True);
1774   const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True);
1775
1776   Tint aFrontLightingModel = anAspectFace->Context().IntFront.color_mask;
1777   const TEL_COLOUR* anInteriorColor = &anAspectFace->Context().IntFront.matcol;
1778   const TEL_COLOUR* anEdgeColor = &anAspectFace->AspectEdge()->Color();
1779   const TEL_COLOUR* aLineColor = &anAspectLine->Color();
1780
1781   // Use highlight colors
1782   if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
1783   {                         
1784     anEdgeColor = anInteriorColor = aLineColor = theWorkspace->HighlightColor;
1785     aFrontLightingModel = 0;
1786   }
1787
1788   DrawArray (aFrontLightingModel,
1789              anAspectFace->Context().InteriorStyle,
1790              anAspectFace->Context().Edge,
1791              anInteriorColor,
1792              aLineColor,
1793              anEdgeColor,
1794              &anAspectFace->Context().IntFront,
1795              theWorkspace);
1796
1797   switch (myPArray->type)
1798   {
1799     case TelPointsArrayType:
1800     case TelPolylinesArrayType:
1801     case TelSegmentsArrayType:
1802     {
1803       if (theWorkspace->NamedStatus & OPENGL_NS_TEXTURE)
1804         EnableTexture();
1805     }
1806   }
1807 }