0022819: Redesign of OpenGl driver
[occt.git] / src / OpenGl / OpenGl_PrimitiveArray.cxx
index 70aa0f2..d1756ab 100755 (executable)
-/*
-File OpenGl_PrimitiveArray.c
-
-Created 16/06/2000 :  ATS : G005 : Modified version of OpenGl_indexpolygons.c, which use glDrawArrays or glDrawElements for rendering of primitive
-21.06.03 : SAN : suppress display at all in animation mode if degenartion ratio == 1 (FULL_DEGENER)
-03.07.03 : SAN : draw_degenerates_as_lines() function - all client states disabled except GL_VERTEX_ARRAY
-in order to avoid exceptions in animation mode (OCC3192)
-*/
-
-#define xOGLBUG         /* UNFORTUNATLY the edge flags are attached to vertexes 
-and not to the edges. So the edge visibillity flags array 
-is not usable.
-*/
-
-#define xPRINT
-
-#define TEST
-
-#define FULL_DEGENER
-#define OCC3192
-
-
-#ifndef OGL_Max
-#define OGL_Max(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
-#ifndef OGL_Rand
-static unsigned long vRand = 1L;
-#define OGL_Rand() (vRand = vRand * 214013L + 2531011L)
-#endif
-
-
-#define OCC7833         /* ASL 26/01/05 transparency of polygon with colors assigned to vertices */
-
-/*----------------------------------------------------------------------*/
-/*
-* Includes
-*/ 
+// File:      OpenGl_PrimitiveArray.cxx
+// Created:   13 July 2011
+// Author:    Sergey ZERCHANINOV
+// Copyright: OPEN CASCADE 2011
 
 #include <OpenGl_tgl_all.hxx>
+#include <OpenGl_PrimitiveArray.hxx>
 
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <iostream>
-
-#include <OpenGl_cmn_varargs.hxx>
-#include <OpenGl_telem_attri.hxx>
-#include <OpenGl_tsm.hxx>
-#include <OpenGl_telem.hxx>
-#include <OpenGl_telem_util.hxx>
-#include <OpenGl_telem_highlight.hxx>
-#include <OpenGl_telem_inquire.hxx>
-#include <OpenGl_telem_view.hxx>
-#include <OpenGl_tgl_funcs.hxx>
-#include <OpenGl_LightBox.hxx>
-#include <OpenGl_TextureBox.hxx>
+#include <OpenGl_AspectFace.hxx>
+#include <OpenGl_GraphicDriver.hxx>
+#include <OpenGl_Memory.hxx>
 #include <OpenGl_ResourceCleaner.hxx>
 #include <OpenGl_ResourceVBO.hxx>
+#include <OpenGl_Structure.hxx>
+#include <OpenGl_TextureBox.hxx>
+
 #include <InterfaceGraphic_PrimitiveArray.hxx>
-#include <OpenGl_Memory.hxx>
-#include <Standard.hxx>
-
-# include <float.h>
-# define DEF_DS_INTERNAL
-# include <OpenGl_degeneration.hxx>
-
-#include <OpenGl_Extension.hxx>
-
-extern GLboolean g_fBitmap;
-
-typedef CALL_DEF_PARRAY *call_def_parray;
-
-#define GL_ARRAY_BUFFER_ARB           0x8892
-#define GL_STATIC_DRAW_ARB            0x88E4
-#define GL_ELEMENTS_ARRAY_BUFFER_ARB  0x8893
-#define GL_EDGE_FLAG_ARRAY_EXT        0x8079
-
-#ifdef WNT
-typedef void (APIENTRY* PFNGLBINDBUFFERARBPROC)    (GLenum target, GLuint buffer);
-typedef void (APIENTRY* PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
-typedef void (APIENTRY* PFNGLGENBUFFERSARBPROC)    (GLsizei n, GLuint *buffers);
-typedef void (APIENTRY* PFNGLBUFFERDATAARBPROC)    (GLenum target, int size, const GLvoid *data, GLenum usage);
-#else//WNT
-typedef void (*PFNGLBINDBUFFERARBPROC)    (GLenum target, GLuint buffer);
-typedef void (*PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
-typedef void (*PFNGLGENBUFFERSARBPROC)    (GLsizei n, GLuint *buffers);
-#if defined ( __sgi ) 
-typedef void (*PFNGLBUFFERDATAARBPROC)    (GLenum target, int size, const GLvoid *data, GLenum usage);
-#else                                                              
-typedef void (*PFNGLBUFFERDATAARBPROC)    (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);
-#endif
-
-#endif//WNT
-
-PFNGLGENBUFFERSARBPROC    glVBOGenBuffersARB    = NULL; // VBO Name Generation Procedure
-PFNGLBINDBUFFERARBPROC    glVBOBindBufferARB    = NULL; // VBO Bind Procedure
-PFNGLBUFFERDATAARBPROC    glVBOBufferDataARB    = NULL; // VBO Data Loading Procedure
-PFNGLDELETEBUFFERSARBPROC glVBODeleteBuffersARB = NULL; // VBO Data Deleting Procedure
-
-int VBOExtension = 0;
-int VBOenabled = 1;
-
-#define VBO_NOT_INITIALIZED  -1
-#define VBO_ERROR             0
-#define VBO_OK                1
-
-#ifndef WNT
-#define glGetProcAddress( x )  glXGetProcAddress( (const GLubyte*) x )
-#else
-#define glGetProcAddress( x )  wglGetProcAddress( x )
-#endif
-
-void clearRAMMemory( CALL_DEF_PARRAY* p )
+
+enum
 {
-    if( p->bufferVBO[VBOEdges] ){
-      Standard::Free((Standard_Address&)p->edges);
-      p->edges = NULL;
-    }
-    if( p->bufferVBO[VBOVertices] ){
-      Standard::Free((Standard_Address&)p->vertices);
-      p->vertices = NULL;
-    }
-    if( p->bufferVBO[VBOVcolours] ){
-      Standard::Free((Standard_Address&)p->vcolours);
-      p->vcolours = NULL;
-    }
-    if( p->bufferVBO[VBOVnormals] ){
-      Standard::Free((Standard_Address&)p->vnormals);
-      p->vnormals = NULL;
-    }
-    if( p->bufferVBO[VBOVtexels] ){
-      Standard::Free((Standard_Address&)p->vtexels);
-      p->vtexels = NULL;
-    }
-    if( p->edge_vis ){
-      Standard::Free((Standard_Address&)p->edge_vis);
-      p->edge_vis = NULL;
-    }
-}
+  VBO_NOT_INITIALIZED = -1,
+  VBO_ERROR           =  0,
+  VBO_OK              =  1
+};
+
+namespace
+{
+  static unsigned long vRand = 1L;
+  #define OGL_Rand() (vRand = vRand * 214013L + 2531011L)
+};
 
-void clearGraphicRAMMemory( CALL_DEF_PARRAY* p )
+// =======================================================================
+// function : clearMemoryOwn
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::clearMemoryOwn() const
 {
-  if( p->bufferVBO[VBOEdges] ){
-    glVBODeleteBuffersARB( 1 , &p->bufferVBO[VBOEdges]);
+  if (myPArray->bufferVBO[VBOEdges] != 0)
+  {
+    Standard::Free ((Standard_Address& )myPArray->edges);
+    myPArray->edges = NULL;
   }
-  if( p->bufferVBO[VBOVertices] ){
-    glVBODeleteBuffersARB( 1 , &p->bufferVBO[VBOVertices]);
+  if (myPArray->bufferVBO[VBOVertices] != 0)
+  {
+    Standard::Free ((Standard_Address& )myPArray->vertices);
+    myPArray->vertices = NULL;
   }
-  if( p->bufferVBO[VBOVcolours] ){
-    glVBODeleteBuffersARB( 1 , &p->bufferVBO[VBOVcolours]);
+  if (myPArray->bufferVBO[VBOVcolours] != 0)
+  {
+    Standard::Free ((Standard_Address& )myPArray->vcolours);
+    myPArray->vcolours = NULL;
   }
-  if( p->bufferVBO[VBOVnormals] ){
-    glVBODeleteBuffersARB( 1 , &p->bufferVBO[VBOVnormals]);
-  } 
-  if( p->bufferVBO[VBOVtexels] ){
-    glVBODeleteBuffersARB( 1 , &p->bufferVBO[VBOVtexels]);
+  if (myPArray->bufferVBO[VBOVnormals] != 0)
+  {
+    Standard::Free ((Standard_Address& )myPArray->vnormals);
+    myPArray->vnormals = NULL;
+  }
+  if (myPArray->bufferVBO[VBOVtexels] != 0)
+  {
+    Standard::Free ((Standard_Address& )myPArray->vtexels);
+    myPArray->vtexels = NULL;
+  }
+  if (myPArray->edge_vis != NULL) /// ????
+  {
+    Standard::Free ((Standard_Address& )myPArray->edge_vis);
+    myPArray->edge_vis = NULL;
   }
-  glVBOBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); 
-  glVBOBindBufferARB(GL_ELEMENTS_ARRAY_BUFFER_ARB, 0); 
 }
 
-int checkSizeForGraphicMemory( CALL_DEF_PARRAY* p )
+// =======================================================================
+// function : clearMemoryGL
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlContext) const
 {
-  if( GL_OUT_OF_MEMORY == glGetError() ){
-    p->flagBufferVBO = VBO_ERROR;
-    clearGraphicRAMMemory(p);
+  if (myPArray->bufferVBO[VBOEdges] != 0)
+  {
+    theGlContext->arbVBO->glDeleteBuffersARB (1, &myPArray->bufferVBO[VBOEdges]);
+  }
+  if (myPArray->bufferVBO[VBOVertices] != 0)
+  {
+    theGlContext->arbVBO->glDeleteBuffersARB (1, &myPArray->bufferVBO[VBOVertices]);
+  }
+  if (myPArray->bufferVBO[VBOVcolours] != 0)
+  {
+    theGlContext->arbVBO->glDeleteBuffersARB (1, &myPArray->bufferVBO[VBOVcolours]);
   }
-  else 
-    p->flagBufferVBO = VBO_OK;
-  return p->flagBufferVBO ;
+  if (myPArray->bufferVBO[VBOVnormals] != 0)
+  {
+    theGlContext->arbVBO->glDeleteBuffersARB (1, &myPArray->bufferVBO[VBOVnormals]);
+  } 
+  if (myPArray->bufferVBO[VBOVtexels] != 0)
+  {
+    theGlContext->arbVBO->glDeleteBuffersARB (1, &myPArray->bufferVBO[VBOVtexels]);
+  }
+  theGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0); 
+  theGlContext->arbVBO->glBindBufferARB (GL_ELEMENTS_ARRAY_BUFFER_ARB, 0); 
 }
 
-int initVBO()
+// =======================================================================
+// function : checkSizeForGraphicMemory
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_PrimitiveArray::checkSizeForGraphicMemory (const Handle(OpenGl_Context)& theGlContext) const
 {
-  if(CheckExtension((char *)"GL_ARB_vertex_buffer_object",(const char *)glGetString( GL_EXTENSIONS ))){
-    glVBOGenBuffersARB = (PFNGLGENBUFFERSARBPROC) glGetProcAddress("glGenBuffersARB");
-    glVBOBindBufferARB = (PFNGLBINDBUFFERARBPROC) glGetProcAddress("glBindBufferARB");
-    glVBOBufferDataARB = (PFNGLBUFFERDATAARBPROC) glGetProcAddress("glBufferDataARB");
-    glVBODeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) glGetProcAddress("glDeleteBuffersARB");
-    VBOExtension = 1;
-    return 1;
-  }
-  return 0;
+  if (glGetError() == GL_OUT_OF_MEMORY)
+  {
+    myPArray->flagBufferVBO = VBO_ERROR;
+    clearMemoryGL (theGlContext);
+  }
+  else
+  {
+    myPArray->flagBufferVBO = VBO_OK;
+  }
+  return myPArray->flagBufferVBO == VBO_OK;
 }
 
-static void  BuildVBO( CALL_DEF_PARRAY* p )
+// =======================================================================
+// function : BuildVBO
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_PrimitiveArray::BuildVBO (const Handle(OpenGl_Workspace)& theWorkspace) const
 {
   int size_reqd = 0;
-  if( p->edges ){
-    size_reqd = ( p->num_edges * sizeof( Tint ) );
-    glVBOGenBuffersARB( 1, &p->bufferVBO[VBOEdges] );   
-    glVBOBindBufferARB( GL_ELEMENTS_ARRAY_BUFFER_ARB, p->bufferVBO[VBOEdges] );
-    glVBOBufferDataARB( GL_ELEMENTS_ARRAY_BUFFER_ARB, size_reqd , p->edges, GL_STATIC_DRAW_ARB );
-    if( checkSizeForGraphicMemory( p ) == VBO_ERROR ) 
-      return;
+  const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
+  if (myPArray->edges != NULL)
+  {
+    size_reqd = myPArray->num_edges * sizeof(Tint);
+    aGlContext->arbVBO->glGenBuffersARB (1, &myPArray->bufferVBO[VBOEdges]);   
+    aGlContext->arbVBO->glBindBufferARB (GL_ELEMENTS_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOEdges]);
+    aGlContext->arbVBO->glBufferDataARB (GL_ELEMENTS_ARRAY_BUFFER_ARB, size_reqd, myPArray->edges, GL_STATIC_DRAW_ARB);
+    if (!checkSizeForGraphicMemory (aGlContext))
+      return Standard_False;
   }
 
-  if( p->vertices ){
-    size_reqd = ( p->num_vertexs * sizeof( TEL_POINT ) );
-    glVBOGenBuffersARB( 1, &p->bufferVBO[VBOVertices]); 
-    glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB, p->bufferVBO[VBOVertices] );
-    glVBOBufferDataARB( GL_ARRAY_BUFFER_ARB, size_reqd , p->vertices, GL_STATIC_DRAW_ARB );
-    if( checkSizeForGraphicMemory( p ) == VBO_ERROR ) 
-      return;
+  if (myPArray->vertices != NULL)
+  {
+    size_reqd = myPArray->num_vertexs * sizeof(TEL_POINT);
+    aGlContext->arbVBO->glGenBuffersARB (1, &myPArray->bufferVBO[VBOVertices]);
+    aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVertices]);
+    aGlContext->arbVBO->glBufferDataARB (GL_ARRAY_BUFFER_ARB, size_reqd, myPArray->vertices, GL_STATIC_DRAW_ARB);
+    if (!checkSizeForGraphicMemory (aGlContext))
+      return Standard_False;
   }
 
-  if( p->vcolours ){
-    size_reqd = ( p->num_vertexs * sizeof( Tint ) );
-    glVBOGenBuffersARB( 1, &p->bufferVBO[VBOVcolours] );
-    glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB, p->bufferVBO[VBOVcolours]); 
-    glVBOBufferDataARB( GL_ARRAY_BUFFER_ARB, size_reqd , p->vcolours, GL_STATIC_DRAW_ARB );
-    if( checkSizeForGraphicMemory( p ) == VBO_ERROR ) 
-      return;
+  if (myPArray->vcolours != NULL)
+  {
+    size_reqd = myPArray->num_vertexs * sizeof(Tint);
+    aGlContext->arbVBO->glGenBuffersARB (1, &myPArray->bufferVBO[VBOVcolours]);
+    aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVcolours]); 
+    aGlContext->arbVBO->glBufferDataARB (GL_ARRAY_BUFFER_ARB, size_reqd, myPArray->vcolours, GL_STATIC_DRAW_ARB);
+    if (!checkSizeForGraphicMemory (aGlContext))
+      return Standard_False;
   }
 
-  if( p->vnormals ){
-    size_reqd = ( p->num_vertexs * sizeof( TEL_POINT ) );
-    glVBOGenBuffersARB( 1, &p->bufferVBO[VBOVnormals] ); 
-    glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB, p->bufferVBO[VBOVnormals] );
-    glVBOBufferDataARB( GL_ARRAY_BUFFER_ARB, size_reqd , p->vnormals, GL_STATIC_DRAW_ARB );
-    if( checkSizeForGraphicMemory( p ) == VBO_ERROR) 
-      return;
+  if (myPArray->vnormals != NULL)
+  {
+    size_reqd = myPArray->num_vertexs * sizeof(TEL_POINT);
+    aGlContext->arbVBO->glGenBuffersARB (1, &myPArray->bufferVBO[VBOVnormals]);
+    aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVnormals]);
+    aGlContext->arbVBO->glBufferDataARB (GL_ARRAY_BUFFER_ARB, size_reqd, myPArray->vnormals, GL_STATIC_DRAW_ARB);
+    if (!checkSizeForGraphicMemory (aGlContext))
+      return Standard_False;
   }
 
-  if( p->vtexels ){
-    size_reqd = ( p->num_vertexs * sizeof( TEL_TEXTURE_COORD ) );
-    glVBOGenBuffersARB( 1, &p->bufferVBO[VBOVtexels] ); 
-    glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB, p->bufferVBO[VBOVtexels] ); 
-    glVBOBufferDataARB( GL_ARRAY_BUFFER_ARB, size_reqd , p->vtexels , GL_STATIC_DRAW_ARB );
-    if( checkSizeForGraphicMemory( p ) == VBO_ERROR ) 
-      return;
-  } 
-
-  if( p->flagBufferVBO == VBO_OK )
-    clearRAMMemory(p);
-
-  //specify context for VBO resource
-  p->contextId = (Standard_Address)GET_GL_CONTEXT();
-
-}
-
-/*----------------------------------------------------------------------*/
-/*
-* Constantes
-*/ 
-
-/*----------------------------------------------------------------------*/
-/*
-* Prototypes
-*/ 
-
-static  TStatus  ParrayDisplay( TSM_ELEM_DATA, Tint, cmn_key* );
-static  TStatus  ParrayAdd( TSM_ELEM_DATA, Tint, cmn_key* );
-static  TStatus  ParrayDelete( TSM_ELEM_DATA, Tint, cmn_key* );
-static  TStatus  ParrayPrint( TSM_ELEM_DATA, Tint, cmn_key* );
-static  TStatus  ParrayInquire( TSM_ELEM_DATA, Tint, cmn_key* );
-
-/*static  GLboolean       lighting_mode;*/
-
-static void draw_array(
-                       call_def_parray,
-                       Tint,          /* highlight_flag */
-                       Tint,          /* front_lighting_model,  */
-                       Tint,          /* interior_style,  */
-                       Tint,          /* edge_flag,  */
-                       tel_colour,    /* interior_colour, */
-                       tel_colour,    /* line_colour, */
-                       tel_colour     /* edge_colour, */
-#ifdef OCC7833
-                       ,tel_surf_prop
-#endif
-                       );
-
-static void draw_edges                 ( call_def_parray, tel_colour );
-static void draw_degenerates_as_points ( call_def_parray, tel_colour );
-static void draw_degenerates_as_lines  ( call_def_parray, tel_colour );
-static void draw_degenerates_as_bboxs  ( call_def_parray, tel_colour );
-
-static  TStatus  (*MtdTbl[])( TSM_ELEM_DATA, Tint, cmn_key* ) =
-{
-  NULL,             /* PickTraverse */
-  ParrayDisplay,
-  ParrayAdd,
-  ParrayDelete,
-  0,
-  0
-};
-static GLenum draw_mode;
-
-/*----------------------------------------------------------------------*/
-/*
-* Variables externes
-*/
-
-extern  Tint  ForbidSetTextureMapping; /* currently defined in tsm/tsm.c */
-
-extern int   g_nDegenerateModel;
-extern float g_fSkipRatio;
+  if (myPArray->vtexels)
+  {
+    size_reqd = myPArray->num_vertexs * sizeof(TEL_TEXTURE_COORD);
+    aGlContext->arbVBO->glGenBuffersARB (1, &myPArray->bufferVBO[VBOVtexels]);
+    aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVtexels]);
+    aGlContext->arbVBO->glBufferDataARB (GL_ARRAY_BUFFER_ARB, size_reqd, myPArray->vtexels, GL_STATIC_DRAW_ARB);
+    if (!checkSizeForGraphicMemory (aGlContext))
+      return Standard_False;
+  }
 
-/*----------------------------------------------------------------------*/
+  if (myPArray->flagBufferVBO == VBO_OK)
+    clearMemoryOwn();
 
-MtblPtr
-TelParrayInitClass( TelType* el )
-{
-  *el = TelParray;
-  return MtdTbl;
+  // specify context for VBO resource
+  myPArray->contextId = (Standard_Address )theWorkspace->GetGContext();
+  return Standard_True;
 }
 
-/*----------------------------------------------------------------------*/
-
-static  TStatus
-ParrayAdd( TSM_ELEM_DATA d, Tint n, cmn_key *k )
+// =======================================================================
+// function : DrawArrays
+// purpose  : Auxiliary method to split Feedback/Normal rendering modes
+// =======================================================================
+inline void DrawArrays (const Handle(OpenGl_Workspace)& theWorkspace,
+                        const CALL_DEF_PARRAY* thePArray,
+                        const Standard_Boolean theIsFeedback,
+                        GLenum  theMode,
+                        GLint   theFirst,
+                        GLsizei theCount)
 {
+  if (!theIsFeedback)
+  {
+    glDrawArrays (theMode, theFirst, theCount);
+    return;
+  }
 
-  if( k[0]->id != PARRAY_ID ) return TFailure;
-
-  ((tsm_elem_data)(d.pdata))->pdata = k[0]->data.pdata;
-
-  return TSuccess;
+  glBegin (theMode);
+  for (int anIter = theFirst; anIter < (theFirst + theCount); ++anIter)
+  {
+    if (thePArray->vnormals != NULL)
+      glNormal3fv (thePArray->vnormals[anIter].xyz);
+    if (thePArray->vtexels  != NULL && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
+      glTexCoord3fv (thePArray->vtexels[anIter].xy);
+    if (thePArray->vertices != NULL)
+      glVertex3fv (thePArray->vertices[anIter].xyz);
+    if (thePArray->vcolours != NULL)
+      glColor4ubv((GLubyte* )thePArray->vcolours[anIter]);
+  }
+  glEnd();
 }
 
-/*----------------------------------------------------------------------*/
-
-static  TStatus
-ParrayDisplay( TSM_ELEM_DATA data, Tint n, cmn_key *k )
+// =======================================================================
+// function : DrawElements
+// purpose  : Auxiliary method to split Feedback/Normal rendering modes
+// =======================================================================
+inline void DrawElements (const Handle(OpenGl_Workspace)& theWorkspace,
+                          const CALL_DEF_PARRAY* thePArray,
+                          const Standard_Boolean theIsFeedback,
+                          GLenum  theMode,
+                          GLsizei theCount,
+                          GLenum* theIndices)
 {
-  CMN_KEY       k11, k12, k17, k18, k111, k114, k115;
-
-  Tint           front_lighting_model;
-  Tint           interior_style;
-  TEL_COLOUR     interior_colour;
-  TEL_COLOUR     edge_colour;
-  TEL_COLOUR     line_colour;
-  Tint           edge_flag;
-
-#ifdef OCC7833
-  CMN_KEY        k117;
-  TEL_SURF_PROP  prop;
-#endif
-
-  call_def_parray d = (call_def_parray)data.pdata;
-
-  k12.id          = TelInteriorReflectanceEquation;
-  k17.id          = TelInteriorStyle;
-  k18.id          = TelEdgeFlag;
-  k111.id         = TelInteriorColour;
-  k111.data.pdata = &interior_colour;
-  k114.id         = TelEdgeColour;
-  k114.data.pdata = &edge_colour;
-  k115.id         = TelPolylineColour;
-  k115.data.pdata = &line_colour;
-
-#ifdef OCC7833
-  k117.id         = TelSurfaceAreaProperties;
-  k117.data.pdata = &prop;
-#endif
-
-#ifdef OCC7833
-  TsmGetAttri( 7, &k12, &k17, &k18, &k111, &k114, &k115, &k117 );
-#else
-  TsmGetAttri( 6, &k12, &k17, &k18, &k111, &k114, &k115 );
-#endif
-
-  front_lighting_model     = k12.data.ldata;
-  interior_style           = k17.data.ldata;
-  edge_flag                = k18.data.ldata;
-
-#ifdef PRINT
-  printf("ParrayDisplay type %d\n",d->type); 
-#endif
-
-  /* 
-  * Use highlight colours 
-  */
-
-  if( k[0]->id == TOn ) {
-    TEL_HIGHLIGHT  hrep;
-
-    k11.id = TelHighlightIndex;
-    TsmGetAttri( 1, &k11 );
-    if( TelGetHighlightRep( TglActiveWs, k11.data.ldata, &hrep ) == TSuccess ) {
-      if( hrep.type == TelHLForcedColour ) {
-        edge_colour = interior_colour = line_colour = hrep.col;
-        front_lighting_model = CALL_PHIGS_REFL_NONE;
-      } else if( hrep.type == TelHLColour ) {
-        edge_colour = hrep.col;
-        k[0]->id = TOff;
-      }
-    } else {
-      TelGetHighlightRep( TglActiveWs, 0, &hrep );
-      if( hrep.type == TelHLForcedColour ) {
-        edge_colour = interior_colour = line_colour = hrep.col;
-        front_lighting_model = CALL_PHIGS_REFL_NONE;
-      } else if( hrep.type == TelHLColour ) {
-        edge_colour = hrep.col;
-        k[0]->id = TOff;
-      }
-    }
+  if (!theIsFeedback)
+  {
+    glDrawElements (theMode, theCount, GL_UNSIGNED_INT, theIndices);
+    return;
   }
 
-  draw_array( d, k[0]->id,
-    front_lighting_model,
-    interior_style,
-    edge_flag,     
-    &interior_colour,
-    &line_colour,
-    &edge_colour
-#ifdef OCC7833
-    ,&prop
-#endif
-    );
-
-  return TSuccess;
-
-}
-
-/*----------------------------------------------------------------------*/
-
-static void 
-draw_primitive_array( call_def_parray p, GLenum mode, GLint first, GLsizei count )
-{
-  int i;
-  glBegin( mode );
-  for( i=first; i<(first + count); i++ ){
-    if( p->vnormals )
-      glNormal3fv( p->vnormals[i].xyz );
-    if( p->vtexels && !ForbidSetTextureMapping )
-      glTexCoord3fv( p->vtexels[i].xy );
-    if( p->vertices )
-      glVertex3fv( p->vertices[i].xyz );
-    if ( p->vcolours )
-      glColor4ubv( (GLubyte*) p->vcolours[i] );
+  GLenum anIndex;
+  glBegin (theMode);
+  for (GLsizei anIter = 0; anIter < theCount; ++anIter)
+  {
+    anIndex = theIndices[anIter];
+    if (thePArray->vnormals != NULL)
+      glNormal3fv (thePArray->vnormals[anIndex].xyz);
+    if (thePArray->vtexels != NULL && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
+      glTexCoord3fv (thePArray->vtexels[anIndex].xy);
+    if (thePArray->vertices != NULL)
+      glVertex3fv (thePArray->vertices[anIndex].xyz);
+    if (thePArray->vcolours != NULL)
+      glColor4ubv ((GLubyte* )thePArray->vcolours[anIndex]);
   }
   glEnd();
 }
 
-/*----------------------------------------------------------------------*/
-static void 
-draw_primitive_elements( call_def_parray p, GLenum mode, GLsizei count, GLenum type, GLenum *indices )
+// =======================================================================
+// function : DrawArray
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawArray (Tint theLightingModel,
+                                       const Aspect_InteriorStyle theInteriorStyle,
+                                       Tint theEdgeFlag,
+                                       const TEL_COLOUR* theInteriorColour,
+                                       const TEL_COLOUR* theLineColour,
+                                       const TEL_COLOUR* theEdgeColour,
+                                       const OPENGL_SURF_PROP* theFaceProp,
+                                       const Handle(OpenGl_Workspace)& theWorkspace) const
 {
-  int i;
-  GLenum index;
-  glBegin( mode );
-  for( i=0; i<count; i++ ){
-    index = indices[i];
-    if( p->vnormals )
-      glNormal3fv( p->vnormals[index].xyz );
-    if( p->vtexels && !ForbidSetTextureMapping )
-      glTexCoord3fv( p->vtexels[index].xy );
-    if( p->vertices ) 
-      glVertex3fv( p->vertices[index].xyz );
-     if ( p->vcolours ) 
-      glColor4ubv( (GLubyte*) p->vcolours[index] );
-  }
-  glEnd();
-}
-/*----------------------------------------------------------------------*/
-static void
-draw_array( call_def_parray p, Tint hflag,
-             Tint lighting_model,
-             Tint interior_style,
-             Tint edge_flag,
-             tel_colour interior_colour,
-             tel_colour line_colour,
-             tel_colour edge_colour
-#ifdef OCC7833
-             ,tel_surf_prop prop
-#endif
-             ){
+  const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
+
   Tint i,n;
   Tint transp = 0;
   GLint renderMode;
-  /* Following pointers have been provided for performance improvement */
-  tel_colour pfc;
-  Tint * pvc;
-
-  pvc = p->vcolours;
-  pfc = p->fcolours;
-
-#ifdef OCC7833
-  if( pvc ){
-    for( i=0; i<p->num_vertexs; i++ ){
-      transp = (int)(prop->trans * 255.);
-#if defined (sparc) || defined (__sparc__) || defined (__sparc) 
-      pvc[i] = ( pvc[i] & 0xffffff00 );
-      pvc[i] += transp ;
-                       
-#else     
-      pvc[i] = ( pvc[i] & 0x00ffffff );
+  // Following pointers have been provided for performance improvement
+  tel_colour pfc = myPArray->fcolours;
+  Tint* pvc = myPArray->vcolours;
+  if (pvc != NULL)
+  {
+    for (i = 0; i < myPArray->num_vertexs; ++i)
+    {
+      transp = int(theFaceProp->trans * 255.0f);
+    #if defined (sparc) || defined (__sparc__) || defined (__sparc) 
+      pvc[i] = (pvc[i] & 0xffffff00);
+      pvc[i] += transp;
+    #else     
+      pvc[i] = (pvc[i] & 0x00ffffff);
       pvc[i] += transp << 24;
-#endif
+    #endif
     }
   }
-#endif
 
-  switch( p->type ) {
+  switch (myPArray->type)
+  {
     case TelPointsArrayType:
-      draw_mode = GL_POINTS; 
-      glColor3fv( line_colour->rgb );
-      break;
     case TelPolylinesArrayType:
-      draw_mode = GL_LINE_STRIP; 
-      glColor3fv( line_colour->rgb );
-      break;
     case TelSegmentsArrayType:
-      draw_mode = GL_LINES;
-      glColor3fv( line_colour->rgb );
+      glColor3fv (theLineColour->rgb);
       break;
     case TelPolygonsArrayType:
-      draw_mode = GL_POLYGON;
-      glColor3fv( interior_colour->rgb );
-      break;
     case TelTrianglesArrayType:
-      draw_mode = GL_TRIANGLES;
-      glColor3fv( interior_colour->rgb );
-      break;
     case TelQuadranglesArrayType:
-      draw_mode = GL_QUADS;
-      glColor3fv( interior_colour->rgb );
-      break;
     case TelTriangleStripsArrayType:
-      draw_mode = GL_TRIANGLE_STRIP;
-      glColor3fv( interior_colour->rgb );
-      break;
     case TelQuadrangleStripsArrayType:
-      draw_mode = GL_QUAD_STRIP;
-      glColor3fv( interior_colour->rgb );
-      break;
     case TelTriangleFansArrayType:
-      draw_mode = GL_TRIANGLE_FAN;
-      glColor3fv( interior_colour->rgb );
+      glColor3fv (theInteriorColour->rgb);
       break;
-    default:
-      return;
   }
 
-   /* OCC11904 -- Temporarily disable environment mapping */
-  if( draw_mode <= GL_LINE_STRIP ){
-    glPushAttrib(GL_ENABLE_BIT);
-    glDisable(GL_TEXTURE_1D);
-    glDisable(GL_TEXTURE_2D);
+  // Temporarily disable environment mapping
+  if (myDrawMode <= GL_LINE_STRIP)
+  {
+    glPushAttrib (GL_ENABLE_BIT);
+    glDisable (GL_TEXTURE_1D);
+    glDisable (GL_TEXTURE_2D);
   }
 
-  if( p->VBOEnabled == -1 ){
-      p->VBOEnabled = VBOenabled;
-      if( VBOExtension == 0)
-        initVBO();
-      if( (VBOExtension == 1) && (p->VBOEnabled != 0))
-        BuildVBO( p );
-  }
-
-
-  #ifdef PRINT
-  printf(" $$$ g_nDegenerateModel %d\n",g_nDegenerateModel);
-  #endif
-  if ( g_nDegenerateModel < 2 && 
-     ( (draw_mode > GL_LINE_STRIP && interior_style != TSM_EMPTY) ||
-       (draw_mode <= GL_LINE_STRIP /*&& !hflag*/)) ) {
-
-    if( hflag == TOn ) {
+  if (theWorkspace->DegenerateModel < 2 &&
+     ((myDrawMode >  GL_LINE_STRIP && theInteriorStyle != Aspect_IS_EMPTY) ||
+      (myDrawMode <= GL_LINE_STRIP)))
+  {
+    if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
+    {
       pfc = NULL;
       pvc = NULL;
     }
 
-    if ( interior_style == TSM_HIDDENLINE) {
-      edge_flag = 1;
+    if (theInteriorStyle == Aspect_IS_HIDDENLINE)
+    {
+      theEdgeFlag = 1;
       pfc = NULL;
       pvc = NULL;
     }
 
-    /*OCC12297 - Sometimes the GL_LIGHTING mode is activated here
-    without LightOn() call for an unknown reason, so it is necessary 
-    to call LightOn() to synchronize LightOn/Off mechanism*/
-    LightOn();
-
-    if( lighting_model == CALL_PHIGS_REFL_NONE || draw_mode <= GL_LINE_STRIP )
-        LightOff();
-
-    glGetIntegerv( GL_RENDER_MODE, &renderMode );
-
-    if ( p->num_vertexs > 0 && p->flagBufferVBO != VBO_OK) {
-      if( renderMode != GL_FEEDBACK ){
-          if( p->vertices ) {
-            glVertexPointer(3, GL_FLOAT, 0, p->vertices);/* array of vertices  */
-            glEnableClientState(GL_VERTEX_ARRAY);
-          }
-
-          if( p->vnormals ) {
-            glNormalPointer(GL_FLOAT, 0, p->vnormals);/* array of normals  */
-            glEnableClientState(GL_NORMAL_ARRAY);
-          }
-
-          if ( p->vtexels) {
-            glTexCoordPointer(2, GL_FLOAT, 0, p->vtexels);/* array of texture coordinates  */
-            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-          }
+    // Sometimes the GL_LIGHTING mode is activated here
+    // without glEnable(GL_LIGHTING) call for an unknown reason, so it is necessary 
+    // to call glEnable(GL_LIGHTING) to synchronize Light On/Off mechanism*
+    if (theLightingModel == 0 || myDrawMode <= GL_LINE_STRIP)
+      glDisable (GL_LIGHTING);
+    else
+      glEnable (GL_LIGHTING);
+
+    glGetIntegerv (GL_RENDER_MODE, &renderMode);
+
+    if (myPArray->num_vertexs > 0
+     && myPArray->flagBufferVBO != VBO_OK
+     && renderMode != GL_FEEDBACK)
+    {
+      if (myPArray->vertices != NULL)
+      {
+        glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices
+        glEnableClientState (GL_VERTEX_ARRAY);
+      }
+      if (myPArray->vnormals != NULL)
+      {
+        glNormalPointer (GL_FLOAT, 0, myPArray->vnormals); // array of normals
+        glEnableClientState (GL_NORMAL_ARRAY);
+      }
+      if (myPArray->vtexels != NULL)
+      {
+        glTexCoordPointer (2, GL_FLOAT, 0, myPArray->vtexels); // array of texture coordinates
+        glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+      }
 
-          if ( pvc ) {
-#ifdef OCC7833
-            glColorPointer(4, GL_UNSIGNED_BYTE, 0, pvc);  /* array of colors */
-#else
-            glColorPointer(3, GL_UNSIGNED_BYTE, 0, pvc);  /* array of colors */
-#endif
-            glEnableClientState(GL_COLOR_ARRAY);
-            glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
-            glEnable(GL_COLOR_MATERIAL);
-          }
+      if (pvc != NULL)
+      {
+        glColorPointer (4, GL_UNSIGNED_BYTE, 0, pvc);  // array of colors
+        glEnableClientState (GL_COLOR_ARRAY);
+        glColorMaterial (GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
+        glEnable (GL_COLOR_MATERIAL);
       }
     }
-
-    //Bindings concrete pointer in accordance with VBO buffer
-    //Using VBO
-    if ( p->num_vertexs > 0 && p->flagBufferVBO == VBO_OK ) {
-      if( p->bufferVBO[VBOVertices] ){
-        glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB, p->bufferVBO[VBOVertices]);
-        glVertexPointer(3, GL_FLOAT, 0, (char *) NULL);// array of vertices 
-        glEnableClientState(GL_VERTEX_ARRAY);
+    else if (myPArray->num_vertexs > 0
+          && myPArray->flagBufferVBO == VBO_OK)
+    {
+      // Bindings concrete pointer in accordance with VBO buffer
+      if (myPArray->bufferVBO[VBOVertices] != 0)
+      {
+        aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVertices]);
+        glVertexPointer (3, GL_FLOAT, 0, NULL); // array of vertices 
+        glEnableClientState (GL_VERTEX_ARRAY);
       }
-
-      if( p->bufferVBO[VBOVnormals] ){
-        glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB,  p->bufferVBO[VBOVnormals]);
-        glNormalPointer(GL_FLOAT, 0, (char *) NULL);// array of normals  
-        glEnableClientState(GL_NORMAL_ARRAY);
+      if (myPArray->bufferVBO[VBOVnormals] != 0)
+      {
+        aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVnormals]);
+        glNormalPointer (GL_FLOAT, 0, NULL); // array of normals  
+        glEnableClientState (GL_NORMAL_ARRAY);
       }
-
-      if ( p->bufferVBO[VBOVtexels] && !ForbidSetTextureMapping ) {
-        glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB,  p->bufferVBO[VBOVtexels]);
-        glTexCoordPointer(2, GL_FLOAT, 0, (char *) NULL);/* array of texture coordinates */
-        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+      if (myPArray->bufferVBO[VBOVtexels] != 0 && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
+      {
+        aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVtexels]);
+        glTexCoordPointer (2, GL_FLOAT, 0, NULL); // array of texture coordinates
+        glEnableClientState (GL_TEXTURE_COORD_ARRAY);
       }
-
-      if ( p->bufferVBO[VBOVcolours] ) {
-        glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB,  p->bufferVBO[VBOVcolours]);
-        glColorPointer( 4, GL_UNSIGNED_BYTE, 0, (char *) NULL);// array of colors 
-        glEnableClientState(GL_COLOR_ARRAY);
-        glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
-        glEnable(GL_COLOR_MATERIAL);
+      if (myPArray->bufferVBO[VBOVcolours] != 0)
+      {
+        aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVcolours]);
+        glColorPointer (4, GL_UNSIGNED_BYTE, 0, NULL); // array of colors 
+        glEnableClientState (GL_COLOR_ARRAY);
+        glColorMaterial (GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
+        glEnable (GL_COLOR_MATERIAL);
       }
     }
+
     // OCC22236 NOTE: draw for all situations:
-    // 1) draw elements from p->bufferVBO[VBOEdges] indicies array
+    // 1) draw elements from myPArray->bufferVBO[VBOEdges] indicies array
     // 2) draw elements from vertice array, when bounds defines count of primitive's verts.
     // 3) draw primitive by vertexes if no edges and bounds array is specified
-    if(  p->flagBufferVBO == VBO_OK ){
-      if ( p->num_edges > 0 && p->bufferVBO[VBOEdges] ) {
-        glVBOBindBufferARB(GL_ELEMENTS_ARRAY_BUFFER_ARB, p->bufferVBO[VBOEdges]); // for edge indices
-        
-        // draw primitives by vertex count with the indicies
-        if( p->num_bounds > 0 ) {
-          Tint* offset = 0;
-          for( i = 0, offset = 0 ; i < p->num_bounds ; i++ ) {
-            glDrawElements(draw_mode, p->bounds[i], GL_UNSIGNED_INT, offset);
-            offset += p->bounds[i]; 
+    if (myPArray->flagBufferVBO == VBO_OK)
+    {
+      if (myPArray->num_edges > 0 && myPArray->bufferVBO[VBOEdges] != 0)
+      {
+        aGlContext->arbVBO->glBindBufferARB (GL_ELEMENTS_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOEdges]); // for edge indices
+        if (myPArray->num_bounds > 0)
+        {
+          // draw primitives by vertex count with the indicies
+          Tint* anOffset = NULL;
+          for (i = 0; i < myPArray->num_bounds; ++i)
+          {
+            glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, anOffset);
+            anOffset += myPArray->bounds[i]; 
           }
         }
-        // draw one (or sequential) primitive by the indicies
-        else {
-          glDrawElements(draw_mode, p->num_edges , GL_UNSIGNED_INT, 0);
+        else
+        {
+          // draw one (or sequential) primitive by the indicies
+          glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, NULL);
         }
       }
-      else if( p->num_bounds > 0 ) {
-        for( i = n = 0 ; i < p->num_bounds ; i ++ ){
-          glDrawArrays(draw_mode, n, p->bounds[i]);
-          n += p->bounds[i];
+      else if (myPArray->num_bounds > 0)
+      {
+        for (i = n = 0; i < myPArray->num_bounds; ++i)
+        {
+          glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
+          n += myPArray->bounds[i];
         }
       }
-      else {
-        glDrawArrays(draw_mode, 0, p->num_vertexs);
+      else
+      {
+        glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
       }
 
-      //bind with 0
-      glVBOBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); 
-      glVBOBindBufferARB(GL_ELEMENTS_ARRAY_BUFFER_ARB, 0); 
+      // bind with 0
+      aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0); 
+      aGlContext->arbVBO->glBindBufferARB (GL_ELEMENTS_ARRAY_BUFFER_ARB, 0); 
     } 
-    else {
-      if( p->num_bounds > 0 ) {
-        if( p->num_edges > 0 ) {
-            for( i=n=0 ; i<p->num_bounds ; i++ ) {
-              if( pfc ) glColor3fv  ( pfc[i].rgb  );
-              if( renderMode == GL_FEEDBACK )
-                draw_primitive_elements( p, draw_mode, p->bounds[i], 
-                                        GL_UNSIGNED_INT,(GLenum*) &p->edges[n]);
-              else
-                glDrawElements( draw_mode, p->bounds[i], 
-                                GL_UNSIGNED_INT, &p->edges[n]);
-              n += p->bounds[i];
-            }
-        } else {
-          for( i=n=0 ; i<p->num_bounds ; i++ ) {
-                if( pfc ) 
-                  glColor3fv  ( pfc[i].rgb  );
-                if( renderMode == GL_FEEDBACK )
-                  draw_primitive_array( p, draw_mode, n, p->bounds[i]);
-                else
-                {
-                  glDrawArrays( draw_mode, n, p->bounds[i]);
-                }
-                n += p->bounds[i];
-              }
+    else
+    {
+      if (myPArray->num_bounds > 0)
+      {
+        if (myPArray->num_edges > 0)
+        {
+          for (i = n = 0; i < myPArray->num_bounds; ++i)
+          {
+            if (pfc != NULL) glColor3fv (pfc[i].rgb);
+            DrawElements (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
+                          myPArray->bounds[i], (GLenum* )&myPArray->edges[n]);
+            n += myPArray->bounds[i];
+          }
+        }
+        else
+        {
+          for (i = n = 0; i < myPArray->num_bounds; ++i)
+          {
+            if (pfc != NULL)
+            {
+              glColor3fv (pfc[i].rgb);
             }
-      } else if( p->num_edges > 0 ) {
-          if( renderMode == GL_FEEDBACK )
-            draw_primitive_elements( p, draw_mode, p->num_edges, 
-                                    GL_UNSIGNED_INT,(GLenum*) &p->edges[0]);
-          else
-         glDrawElements( draw_mode, p->num_edges, GL_UNSIGNED_INT, p->edges);
-      } else {
-            if( renderMode == GL_FEEDBACK )
-            draw_primitive_array( p, draw_mode, 0, p->num_vertexs);
-          else
-            glDrawArrays( draw_mode, 0, p->num_vertexs);
+            DrawArrays (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
+                        n, myPArray->bounds[i]);
+            n += myPArray->bounds[i];
+          }
         }
+      }
+      else if (myPArray->num_edges > 0)
+      {
+        DrawElements (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
+                      myPArray->num_edges, (GLenum* )myPArray->edges);
+      }
+      else
+      {
+        DrawArrays (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
+                    0, myPArray->num_vertexs);
+      }
     }
 
-#ifdef TEST
-    if( p->bufferVBO[VBOVcolours] || pvc ) {
-      glDisable(GL_COLOR_MATERIAL);
-      TelResetMaterial();
+    if (myPArray->bufferVBO[VBOVcolours] != 0 || pvc != NULL)
+    {
+      glDisable (GL_COLOR_MATERIAL);
+      theWorkspace->NamedStatus |= OPENGL_NS_RESMAT; // Reset material
     }
-#endif
-
-    if( p->bufferVBO[VBOVertices] || p->vertices )
-      glDisableClientState(GL_VERTEX_ARRAY);
-    if( p->bufferVBO[VBOVcolours] || p->vcolours )
-      glDisableClientState(GL_COLOR_ARRAY);
-    if( p->bufferVBO[VBOVnormals] || p->vnormals )
-      glDisableClientState(GL_NORMAL_ARRAY);
-    if ( (p->bufferVBO[VBOVtexels] && !ForbidSetTextureMapping ) || p->vtexels )
-      glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
-    if ( g_nDegenerateModel ){
-      if(draw_mode <= GL_LINE_STRIP)
+
+    if (myPArray->bufferVBO[VBOVertices] != 0 || myPArray->vertices != NULL)
+      glDisableClientState (GL_VERTEX_ARRAY);
+    if (myPArray->bufferVBO[VBOVcolours] != 0 || myPArray->vcolours != NULL)
+      glDisableClientState (GL_COLOR_ARRAY);
+    if (myPArray->bufferVBO[VBOVnormals] != 0 || myPArray->vnormals != NULL)
+      glDisableClientState (GL_NORMAL_ARRAY);
+    if ((myPArray->bufferVBO[VBOVtexels] != 0 && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0) || myPArray->vtexels != NULL)
+      glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+
+    if (theWorkspace->DegenerateModel)
+    {
+      if (myDrawMode <= GL_LINE_STRIP)
+      {
         glPopAttrib();
+      }
       return;
     }
   }
 
-  if( edge_flag || g_nDegenerateModel ) 
-    switch ( g_nDegenerateModel ) {
-      default: /* XXX_TDM_NODE or TINY */
-          /*
-            On some NVIDIA graphic cards, using glEdgeFlagPointer() in 
-            combination with VBO ( edge flag data put into a VBO buffer)
-            leads to a crash in a driver. Therefore, edge flags are simply 
-            igonored when VBOs are enabled, so all the edges are drawn if 
-            edge visibility is turned on. In order to draw edges selectively, 
-            either disable VBO or turn off edge visibilty in the current 
-            primitive array and create a separate primitive array (segments) 
-            and put edges to be drawn into it.
-          */
-          draw_edges ( p, edge_flag ? edge_colour : interior_colour );
+  if (theEdgeFlag || theWorkspace->DegenerateModel)
+  {
+    switch (theWorkspace->DegenerateModel)
+    {
+      default: // XXX_TDM_NODE or TINY
+        //  On some NVIDIA graphic cards, using glEdgeFlagPointer() in 
+        //  combination with VBO ( edge flag data put into a VBO buffer)
+        //  leads to a crash in a driver. Therefore, edge flags are simply 
+        //  igonored when VBOs are enabled, so all the edges are drawn if 
+        //  edge visibility is turned on. In order to draw edges selectively, 
+        //  either disable VBO or turn off edge visibilty in the current 
+        //  primitive array and create a separate primitive array (segments) 
+        //  and put edges to be drawn into it.
+        DrawEdges (theEdgeFlag ? theEdgeColour : theInteriorColour, theWorkspace);
+        break;
+      // DegenerateModel(as Lines, Points, BBoxs) are used only without VBO
+      case 2: // XXX_TDM_WIREFRAME
+        if (myPArray->VBOEnabled == 0)
+          DrawDegeneratesAsLines ((theEdgeFlag ? theEdgeColour : theInteriorColour), theWorkspace);
+        break;
+      case 3: // XXX_TDM_MARKER
+        if (myPArray->VBOEnabled == 0)
+          DrawDegeneratesAsPoints ((theEdgeFlag ? theEdgeColour : theInteriorColour), theWorkspace->SkipRatio);
         break;
-        // DegenerateModel(as Lines, Points, BBoxs) are used only without VBO
-          case 2:  /* XXX_TDM_WIREFRAME */
-            if( p->VBOEnabled == 0 )
-              draw_degenerates_as_lines ( p, edge_flag ? edge_colour : interior_colour );
-            break;
-          case 3:  /* XXX_TDM_MARKER */
-            if( p->VBOEnabled == 0  )
-              draw_degenerates_as_points ( p, edge_flag ? edge_colour : interior_colour );
-            break;
-          case 4:  /* XXX_TDM_BBOX */
-            if( p->VBOEnabled == 0  )
-              draw_degenerates_as_bboxs ( p, edge_flag ? edge_colour : interior_colour  );
-            break;
-   }
-
-  if(draw_mode <= GL_LINE_STRIP)
+      case 4: // XXX_TDM_BBOX
+        if (myPArray->VBOEnabled == 0)
+          DrawDegeneratesAsBBoxs (theEdgeFlag ? theEdgeColour : theInteriorColour);
+        break;
+    }
+  }
+
+  if (myDrawMode <= GL_LINE_STRIP)
     glPopAttrib();
 }
 
-/*----------------------------------------------------------------------*/
-
-static  TStatus
-ParrayDelete( TSM_ELEM_DATA data, Tint n, cmn_key *k )
+// =======================================================================
+// function : DrawEdges
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawEdges (const TEL_COLOUR*               theEdgeColour,
+                                       const Handle(OpenGl_Workspace)& theWorkspace) const
 {
-  call_def_parray p = (call_def_parray)data.pdata;
-  if( p->VBOEnabled == VBO_OK ) {
-    OpenGl_ResourceCleaner* resCleaner = OpenGl_ResourceCleaner::GetInstance();
-    if( p->bufferVBO[VBOEdges] )
-      resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOEdges]) ); 
-    if( p->bufferVBO[VBOVertices] )
-      resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOVertices]) ); 
-    if( p->bufferVBO[VBOVcolours] )
-         resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOVcolours]) ); 
-    if( p->bufferVBO[VBOVnormals] )
-      resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOVnormals]) ); 
-    if( p->bufferVBO[VBOVtexels] )
-      resCleaner->AddResource( (GLCONTEXT)p->contextId, new OpenGl_ResourceVBO(p->bufferVBO[VBOVtexels]) ); 
-  }
-
-  return TSuccess;
-}
+  glDisable (GL_LIGHTING);
 
-/*----------------------------------------------------------------------*/
+  const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
+  const OpenGl_AspectLine* anAspectLineOld = NULL;
+  if (myDrawMode > GL_LINE_STRIP)
+  {
+    anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge());
+    theWorkspace->AspectLine (Standard_True);
 
-static void
-draw_edges ( call_def_parray p, tel_colour edge_colour )
-{
-  Tint    i, j, n;
-  Tint    edge_type=0, line_type_preserve=0;
-  Tfloat  edge_width=0, line_width_preserve=0; 
-  /* GLboolean texture_on;*/
+    glPushAttrib (GL_POLYGON_BIT);
+    glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+  }
 
+  Tint i, j, n;
   GLint renderMode;
-  
-  LightOff();
-  if( draw_mode > GL_LINE_STRIP ) { 
-    CMN_KEY k, k1, k2, k3, k4;
-
-    k1.id  = TelPolylineWidth;
-    k2.id  = TelPolylineType;
-    k3.id  = TelEdgeType;
-    k4.id  = TelEdgeWidth;
-    
-    TsmGetAttri( 4, &k1, &k2, &k3, &k4 );
-    
-    line_width_preserve = k1.data.fdata;
-    line_type_preserve  = k2.data.ldata;
-    edge_type           = k3.data.ldata;
-    edge_width          = k4.data.fdata;
-
-    if( line_width_preserve != edge_width ) {
-      k.id = TelPolylineWidth;
-      k.data.fdata = edge_width;
-      TsmSetAttri( 1, &k );
-    }
-    if( line_type_preserve != edge_type ) {
-      k.id = TelPolylineType;
-      k.data.ldata = edge_type;
-      TsmSetAttri( 1, &k );
-    }
-
-    glPushAttrib( GL_POLYGON_BIT );
-    glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); 
-  }
 
   // OCC22236 NOTE: draw edges for all situations:
-  // 1) draw elements with GL_LINE style as edges from p->bufferVBO[VBOEdges] indicies array
+  // 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indicies array
   // 2) draw elements from vertice array, when bounds defines count of primitive's verts.
   // 3) draw primitive's edges by vertexes if no edges and bounds array is specified
-  if(p->flagBufferVBO == VBO_OK)
+  if (myPArray->flagBufferVBO == VBO_OK)
   { 
-    glVBOBindBufferARB( GL_ARRAY_BUFFER_ARB, p->bufferVBO[VBOVertices] );
-    glEnableClientState( GL_VERTEX_ARRAY );
-    glColor3fv( edge_colour->rgb );
-    if ( p->num_edges > 0 && p->bufferVBO[VBOEdges] ) {
-      glVBOBindBufferARB(GL_ELEMENTS_ARRAY_BUFFER_ARB, p->bufferVBO[VBOEdges]); 
-      
+    aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOVertices]);
+    glEnableClientState (GL_VERTEX_ARRAY);
+    glColor3fv (theEdgeColour->rgb);
+    if (myPArray->num_edges > 0 && myPArray->bufferVBO[VBOEdges])
+    {
+      aGlContext->arbVBO->glBindBufferARB (GL_ELEMENTS_ARRAY_BUFFER_ARB, myPArray->bufferVBO[VBOEdges]);
+
       // draw primitives by vertex count with the indicies
-      if( p->num_bounds > 0 ) {
+      if (myPArray->num_bounds > 0)
+      {
         Tint* offset = 0;
-        for( i = 0, offset = 0 ; i < p->num_bounds ; i++ ) {
-          glDrawElements( draw_mode, p->bounds[i], GL_UNSIGNED_INT, offset);
-          offset += p->bounds[i];
+        for (i = 0, offset = 0; i < myPArray->num_bounds; ++i)
+        {
+          glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, offset);
+          offset += myPArray->bounds[i];
         }
       }
       // draw one (or sequential) primitive by the indicies
-      else {
-        glDrawElements( draw_mode, p->num_edges , GL_UNSIGNED_INT, 0);
+      else
+      {
+        glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, NULL);
       }
     }
-    else if( p->num_bounds > 0 ) {
-      for( i = n = 0 ; i < p->num_bounds ; i ++ ){
-        glDrawArrays( draw_mode, n, p->bounds[i]);
-        n += p->bounds[i];
+    else if (myPArray->num_bounds > 0)
+    {
+      for (i = n = 0; i < myPArray->num_bounds; ++i)
+      {
+        glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
+        n += myPArray->bounds[i];
       }
     }
-    else {
-      glDrawArrays( draw_mode, 0, p->num_vertexs);
+    else
+    {
+      glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
     }
 
     // unbind buffers
-    glDisableClientState(GL_VERTEX_ARRAY);
-    glVBOBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
-    glVBOBindBufferARB(GL_ELEMENTS_ARRAY_BUFFER_ARB, 0); 
-  }
-  else {
-
-    glEnableClientState(GL_VERTEX_ARRAY);
-    glVertexPointer(3, GL_FLOAT, 0, p->vertices); /* array of vertices  */
-#ifdef OGLBUG
-      if( p->edge_vis ) {
-        glEnableClientState(GL_EDGE_FLAG_ARRAY);
-        glEdgeFlagPointer( sizeof(Tchar), p->edge_vis);
-      } else
-        glDisableClientState(GL_EDGE_FLAG_ARRAY);
-#endif
-
-   glGetIntegerv( GL_RENDER_MODE, &renderMode );
-
-      glColor3fv( edge_colour->rgb );
-      if( p->num_bounds > 0 ) {
-        if( p->num_edges > 0 ) {
-          for( i=n=0 ; i<p->num_bounds ; i++ ) {
-#ifndef OGLBUG
-            if( p->edge_vis ) {
-              glBegin( draw_mode );
-              for( j=0 ; j<p->bounds[i] ; j++ ) {
-                glEdgeFlag( p->edge_vis[n+j] );
-                glVertex3fv( &p->vertices[p->edges[n+j]].xyz[0] );
-              }
-              glEnd();
-            } else
-#endif
-        if( renderMode == GL_FEEDBACK )
-          draw_primitive_elements( p, draw_mode, p->bounds[i], 
-                                  GL_UNSIGNED_INT, (GLenum*)&p->edges[n]);
-        else
-          glDrawElements( draw_mode, p->bounds[i], 
-                                  GL_UNSIGNED_INT, &p->edges[n]);
-            n += p->bounds[i];
+    glDisableClientState (GL_VERTEX_ARRAY);
+    aGlContext->arbVBO->glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
+    aGlContext->arbVBO->glBindBufferARB (GL_ELEMENTS_ARRAY_BUFFER_ARB, 0);
+  }
+  else
+  {
+    glEnableClientState (GL_VERTEX_ARRAY);
+    glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices
+    glGetIntegerv (GL_RENDER_MODE, &renderMode);
+
+    glColor3fv (theEdgeColour->rgb);
+    if (myPArray->num_bounds > 0)
+    {
+      if (myPArray->num_edges > 0)
+      {
+        for (i = n = 0; i < myPArray->num_bounds; ++i)
+        {
+          if (myPArray->edge_vis)
+          {
+            glBegin (myDrawMode);
+            for (j = 0; j < myPArray->bounds[i]; ++j)
+            {
+              glEdgeFlag (myPArray->edge_vis[n+j]);
+              glVertex3fv (&myPArray->vertices[myPArray->edges[n+j]].xyz[0]);
+            }
+            glEnd();
           }
-        } else {
-          for( i=n=0 ; i<p->num_bounds ; i++ ) {
-        if( renderMode == GL_FEEDBACK )
-          draw_primitive_array( p, draw_mode, n, p->bounds[i]);
-        else
-          glDrawArrays( draw_mode, n, p->bounds[i]);
-            n += p->bounds[i];
+          else
+          {
+            DrawElements (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
+                          myPArray->bounds[i], (GLenum* )&myPArray->edges[n]);
           }
+          n += myPArray->bounds[i];
         }
-      } 
-      else if( p->num_edges > 0 ) {
-#ifndef OGLBUG
-        if( p->edge_vis ) {
-          glBegin( draw_mode );
-          for( i=0 ; i<p->num_edges ; i++ ) {
-            glEdgeFlag( p->edge_vis[i] );
-            glVertex3fv( &p->vertices[p->edges[i]].xyz[0] );
-          }
-          glEnd();
-        } else
-#endif
-      if( renderMode == GL_FEEDBACK )
-        draw_primitive_elements( p, draw_mode, p->num_edges, 
-                                  GL_UNSIGNED_INT,(GLenum*) p->edges);
+      }
       else
-        glDrawElements( draw_mode, p->num_edges, 
-                                  GL_UNSIGNED_INT, p->edges);
-      } else {
-      if( renderMode == GL_FEEDBACK )
-        draw_primitive_array( p, draw_mode, 0, p->num_vertexs);
+      {
+        for (i = n = 0 ; i < myPArray->num_bounds; ++i)
+        {
+          DrawArrays (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
+                      n, myPArray->bounds[i]);
+          n += myPArray->bounds[i];
+        }
+      }
+    } 
+    else if (myPArray->num_edges > 0)
+    {
+      if (myPArray->edge_vis)
+      {
+        glBegin (myDrawMode);
+        for (i = 0; i < myPArray->num_edges; ++i)
+        {
+          glEdgeFlag (myPArray->edge_vis[i]);
+          glVertex3fv (&myPArray->vertices[myPArray->edges[i]].xyz[0]);
+        }
+        glEnd();
+      }
       else
-        glDrawArrays( draw_mode, 0, p->num_vertexs);
+      {
+        DrawElements (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
+                      myPArray->num_edges, (GLenum* )myPArray->edges);
       }
     }
-
-  if( draw_mode > GL_LINE_STRIP ) {
-    CMN_KEY k;
-    if( line_width_preserve != edge_width ) {
-      k.id = TelPolylineWidth;
-      k.data.fdata = line_width_preserve;
-      TsmSetAttri( 1, &k );
-    }
-    if( line_type_preserve != edge_type ) {
-      k.id = TelPolylineType;
-      k.data.ldata = line_type_preserve;
-      TsmSetAttri( 1, &k );
+    else
+    {
+      DrawArrays (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
+                  0, myPArray->num_vertexs);
     }
+  }
+
+  if (myDrawMode > GL_LINE_STRIP)
+  {
+    // Restore line context
+    theWorkspace->SetAspectLine (anAspectLineOld);
     glPopAttrib();
   }
 }
 
-/*----------------------------------------------------------------------*/
-static void draw_degenerates_points_as_points ( call_def_parray p ) { 
-
-  Tint       j;
-  tel_point  pv = p -> vertices;
-
-#ifdef FULL_DEGENER
-  if ( g_fSkipRatio == 1. )
-    return;
-#endif
-
-  for ( j=0 ; j<p->num_vertexs ; j++ ) {
-    glVertex3fv ( &pv[j].xyz[0] );
+// =======================================================================
+// function : DrawDegeneratesPointsAsPoints
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawDegeneratesPointsAsPoints() const
+{ 
+  tel_point pv = myPArray->vertices;
+  for (Tint aVertId = 0; aVertId < myPArray->num_vertexs; ++aVertId)
+  {
+    glVertex3fv (&pv[aVertId].xyz[0]);
   }
-}  
-
-/*----------------------------------------------------------------------*/
-static void draw_degenerates_lines_as_points ( call_def_parray p ) { 
-
-  Tint       j;
-  GLfloat    pt[ 3 ];
-  tel_point  pv = p -> vertices;
+}
 
-#ifdef FULL_DEGENER
-  if ( g_fSkipRatio == 1. )
-    return;
-#endif
-
-  for ( j=0 ; j<p->num_vertexs ; j+=2 ) {
-    pt[0] = pt[1] = pt[2] = 0.;
-    pt[ 0 ] += pv[j].xyz[ 0 ];
-    pt[ 1 ] += pv[j].xyz[ 1 ];
-    pt[ 2 ] += pv[j].xyz[ 2 ];
-    pt[ 0 ] += pv[j+1].xyz[ 0 ];
-    pt[ 1 ] += pv[j+1].xyz[ 1 ];
-    pt[ 2 ] += pv[j+1].xyz[ 2 ];
-    pt[ 0 ] /= 2;
-    pt[ 1 ] /= 2;
-    pt[ 2 ] /= 2;
-    glVertex3fv ( pt );
+// =======================================================================
+// function : DrawDegeneratesLinesAsPoints
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawDegeneratesLinesAsPoints() const
+{
+  GLfloat pt[3];
+  tel_point pv = myPArray->vertices;
+
+  Tint j = 0;
+  while (j < myPArray->num_vertexs)
+  {
+    pt[0] = pv[j].xyz[0];
+    pt[1] = pv[j].xyz[1];
+    pt[2] = pv[j].xyz[2]; ++j;
+    pt[0] += pv[j].xyz[0];
+    pt[1] += pv[j].xyz[1];
+    pt[2] += pv[j].xyz[2]; ++j;
+    pt[0] *= 0.5f;
+    pt[1] *= 0.5f;
+    pt[2] *= 0.5f;
+    glVertex3fv (pt);
   }
 }  
 
-/*----------------------------------------------------------------------*/
-static void draw_degenerates_triangles_as_points ( call_def_parray p ) { 
-
-  Tint       i, j, iv;
-  GLfloat    pt[ 3 ];
-  tel_point  pv = p -> vertices;
-
-#ifdef FULL_DEGENER
-  if ( g_fSkipRatio == 1. )
-    return;
-#endif
-
-  if( p->num_edges > 0 ) {
-    for ( j=0 ; j<p->num_edges ; j+=3 ) {
-      pt[0] = pt[1] = pt[2] = 0.;
-      for ( i=0 ; i<3 ; i++ ) {
-        iv = p->edges[j+i];
-        pt[ 0 ] += pv[iv].xyz[ 0 ];
-        pt[ 1 ] += pv[iv].xyz[ 1 ];
-        pt[ 2 ] += pv[iv].xyz[ 2 ];
+// =======================================================================
+// function : DrawDegeneratesTrianglesAsPoints
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawDegeneratesTrianglesAsPoints() const
+{
+  Tint      i, j, iv;
+  GLfloat   pt[ 3 ];
+  tel_point pv = myPArray->vertices;
+
+  if (myPArray->num_edges > 0)
+  {
+    for (j = 0; j < myPArray->num_edges; j += 3)
+    {
+      iv = myPArray->edges[j];
+      pt[0] = pv[iv].xyz[0];
+      pt[1] = pv[iv].xyz[1];
+      pt[2] = pv[iv].xyz[2];
+      for (i = 1; i < 3; ++i)
+      {
+        iv = myPArray->edges[j+i];
+        pt[0] += pv[iv].xyz[0];
+        pt[1] += pv[iv].xyz[1];
+        pt[2] += pv[iv].xyz[2];
       }
-      pt[ 0 ] /= 3;
-      pt[ 1 ] /= 3;
-      pt[ 2 ] /= 3;
-      glVertex3fv ( pt );
+      pt[0] /= 3.f;
+      pt[1] /= 3.f;
+      pt[2] /= 3.f;
+      glVertex3fv (pt);
     }
-  } else {
-    for ( j=0 ; j<p->num_vertexs ; j+=3 ) {
-      pt[0] = pt[1] = pt[2] = 0.;
-      for ( i=0 ; i<3 ; i++ ) {
-        pt[ 0 ] += pv[j+i].xyz[ 0 ];
-        pt[ 1 ] += pv[j+i].xyz[ 1 ];
-        pt[ 2 ] += pv[j+i].xyz[ 2 ];
+  }
+  else
+  {
+    for (j = 0; j < myPArray->num_vertexs; j += 3)
+    {
+      pt[0] = pv[j].xyz[0];
+      pt[1] = pv[j].xyz[1];
+      pt[2] = pv[j].xyz[2];
+      for (i = 1; i < 3; ++i)
+      {
+        pt[0] += pv[j+i].xyz[0];
+        pt[1] += pv[j+i].xyz[1];
+        pt[2] += pv[j+i].xyz[2];
       }
-      pt[ 0 ] /= 3;
-      pt[ 1 ] /= 3;
-      pt[ 2 ] /= 3;
-      glVertex3fv ( pt );
+      pt[0] /= 3.f;
+      pt[1] /= 3.f;
+      pt[2] /= 3.f;
+      glVertex3fv (pt);
     }
   }
-}  
-
-/*----------------------------------------------------------------------*/
-static void draw_degenerates_trianglestrips_as_points ( call_def_parray p ) { 
-
-  Tint       i, j, k, n;
-  GLfloat    pt[ 3 ];
-  tel_point  pv = p -> vertices;
-
-#ifdef FULL_DEGENER
-  if ( g_fSkipRatio == 1. )
-    return;
-#endif
+}
 
-  if( p->num_bounds > 0 ) {
-    for ( k=n=0 ; k<p->num_bounds ; k++ ) {
-      for ( j=0 ; j<p->bounds[k]-2 ; j++ ) {
-        pt[0] = pt[1] = pt[2] = 0.;
-        for ( i=0 ; i<3 ; i++ ) {
-          pt[ 0 ] += pv[n+j+i].xyz[ 0 ];
-          pt[ 1 ] += pv[n+j+i].xyz[ 1 ];
-          pt[ 2 ] += pv[n+j+i].xyz[ 2 ];
+// =======================================================================
+// function : DrawDegeneratesTrianglesAsPoints
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawDegeneratesTrianglestripsAsPoints() const
+{ 
+  Tint      i, j, k, n;
+  GLfloat   pt[ 3 ];
+  tel_point pv = myPArray->vertices;
+
+  if (myPArray->num_bounds > 0)
+  {
+    for (k = n = 0; k < myPArray->num_bounds; ++k)
+    {
+      for (j = 0; j < myPArray->bounds[k] - 2; ++j)
+      {
+        pt[0] = pv[n+j].xyz[0];
+        pt[1] = pv[n+j].xyz[1];
+        pt[2] = pv[n+j].xyz[2];
+        for (i = 1; i < 3; ++i)
+        {
+          pt[0] += pv[n+j+i].xyz[0];
+          pt[1] += pv[n+j+i].xyz[1];
+          pt[2] += pv[n+j+i].xyz[2];
         }
-        pt[ 0 ] /= 3;
-        pt[ 1 ] /= 3;
-        pt[ 2 ] /= 3;
-        glVertex3fv ( pt );
+        pt[0] /= 3.f;
+        pt[1] /= 3.f;
+        pt[2] /= 3.f;
+        glVertex3fv (pt);
       }
-      n += p->bounds[k];
+      n += myPArray->bounds[k];
     }
-  } else {
-    for ( j=0 ; j<p->num_vertexs-2 ; j++ ) {
-      pt[0] = pt[1] = pt[2] = 0.;
-      for ( i=0 ; i<3 ; i++ ) {
-        pt[ 0 ] += pv[j+i].xyz[ 0 ];
-        pt[ 1 ] += pv[j+i].xyz[ 1 ];
-        pt[ 2 ] += pv[j+i].xyz[ 2 ];
+  }
+  else
+  {
+    for (j = 0; j < myPArray->num_vertexs - 2; ++j)
+    {
+      pt[0] = pv[j].xyz[0];
+      pt[1] = pv[j].xyz[1];
+      pt[2] = pv[j].xyz[2];
+      for (i = 1; i < 3; ++i)
+      {
+        pt[0] += pv[j+i].xyz[0];
+        pt[1] += pv[j+i].xyz[1];
+        pt[2] += pv[j+i].xyz[2];
       }
-      pt[ 0 ] /= 3;
-      pt[ 1 ] /= 3;
-      pt[ 2 ] /= 3;
-      glVertex3fv ( pt );
+      pt[0] /= 3.f;
+      pt[1] /= 3.f;
+      pt[2] /= 3.f;
+      glVertex3fv (pt);
     }
   }
-}  
-
-/*----------------------------------------------------------------------*/
-static void draw_degenerates_polygons_as_points ( call_def_parray p ) { 
-
-  Tint       j, k, n, iv;
-  GLfloat    pt[ 3 ];
-  tel_point  pv = p -> vertices;
-
-#ifdef FULL_DEGENER
-  if ( g_fSkipRatio == 1. )
-    return;
-#endif
+}
 
-  if( p->num_bounds > 0 ) {
-    if( p->num_edges > 0 ) {
-      for ( k=n=0 ; k<p->num_bounds ; k++ ) {
-        pt[0] = pt[1] = pt[2] = 0.;
-        for ( j=0 ; j<p->bounds[k] ; j++ ) {
-          iv = p->edges[n+j];
-          pt[ 0 ] += pv[iv].xyz[ 0 ];
-          pt[ 1 ] += pv[iv].xyz[ 1 ];
-          pt[ 2 ] += pv[iv].xyz[ 2 ];
+// =======================================================================
+// function : DrawDegeneratesPolygonsAsPoints
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawDegeneratesPolygonsAsPoints() const
+{ 
+  Tint      j, k, n, iv;
+  GLfloat   pt[3];
+  tel_point pv = myPArray->vertices;
+
+  if (myPArray->num_bounds > 0)
+  {
+    if (myPArray->num_edges > 0)
+    {
+      for (k = n = 0; k < myPArray->num_bounds; ++k)
+      {
+        pt[0] = pt[1] = pt[2] = 0.0;
+        for (j = 0; j < myPArray->bounds[k]; ++j)
+        {
+          iv = myPArray->edges[n+j];
+          pt[0] += pv[iv].xyz[0];
+          pt[1] += pv[iv].xyz[1];
+          pt[2] += pv[iv].xyz[2];
         }
-        pt[ 0 ] /= p->bounds[k];
-        pt[ 1 ] /= p->bounds[k];
-        pt[ 2 ] /= p->bounds[k];
-        glVertex3fv ( pt );
-        n += p->bounds[k];
+        pt[0] /= myPArray->bounds[k];
+        pt[1] /= myPArray->bounds[k];
+        pt[2] /= myPArray->bounds[k];
+        glVertex3fv (pt);
+        n += myPArray->bounds[k];
       }
-    } else {  
-      for ( k=n=0 ; k<p->num_bounds ; k++ ) {
-        pt[0] = pt[1] = pt[2] = 0.;
-        for ( j=0 ; j<p->bounds[k] ; j++ ) {
-          pt[ 0 ] += pv[n+j].xyz[ 0 ];
-          pt[ 1 ] += pv[n+j].xyz[ 1 ];
-          pt[ 2 ] += pv[n+j].xyz[ 2 ];
+    }
+    else
+    {
+      for (k = n = 0; k < myPArray->num_bounds; ++k)
+      {
+        pt[0] = pt[1] = pt[2] = 0.0;
+        for (j = 0; j < myPArray->bounds[k]; ++j)
+        {
+          pt[0] += pv[n+j].xyz[0];
+          pt[1] += pv[n+j].xyz[1];
+          pt[2] += pv[n+j].xyz[2];
         }
-        pt[ 0 ] /= p->bounds[k];
-        pt[ 1 ] /= p->bounds[k];
-        pt[ 2 ] /= p->bounds[k];
-        glVertex3fv ( pt );
-        n += p->bounds[k];
+        pt[0] /= myPArray->bounds[k];
+        pt[1] /= myPArray->bounds[k];
+        pt[2] /= myPArray->bounds[k];
+        glVertex3fv (pt);
+        n += myPArray->bounds[k];
       }
     }
-  } else if( p->num_edges > 0 ) {
-    pt[0] = pt[1] = pt[2] = 0.;
-    for ( j=0 ; j<p->num_edges ; j++ ) {
-      iv = p->edges[j];
-      pt[ 0 ] += pv[iv].xyz[ 0 ];
-      pt[ 1 ] += pv[iv].xyz[ 1 ];
-      pt[ 2 ] += pv[iv].xyz[ 2 ];
+  }
+  else if (myPArray->num_edges > 0)
+  {
+    pt[0] = pt[1] = pt[2] = 0.0;
+    for (j = 0; j < myPArray->num_edges; ++j)
+    {
+      iv = myPArray->edges[j];
+      pt[0] += pv[iv].xyz[0];
+      pt[1] += pv[iv].xyz[1];
+      pt[2] += pv[iv].xyz[2];
     }
-    pt[ 0 ] /= p->num_edges;
-    pt[ 1 ] /= p->num_edges;
-    pt[ 2 ] /= p->num_edges;
-    glVertex3fv ( pt );
-  } else {
-    pt[0] = pt[1] = pt[2] = 0.;
-    for ( j=0 ; j<p->num_vertexs ; j++ ) {
-      pt[ 0 ] += pv[j].xyz[ 0 ];
-      pt[ 1 ] += pv[j].xyz[ 1 ];
-      pt[ 2 ] += pv[j].xyz[ 2 ];
+    pt[0] /= myPArray->num_edges;
+    pt[1] /= myPArray->num_edges;
+    pt[2] /= myPArray->num_edges;
+    glVertex3fv (pt);
+  }
+  else
+  {
+    pt[0] = pt[1] = pt[2] = 0.0;
+    for (j = 0; j < myPArray->num_vertexs; ++j)
+    {
+      pt[0] += pv[j].xyz[0];
+      pt[1] += pv[j].xyz[1];
+      pt[2] += pv[j].xyz[2];
     }
-    pt[ 0 ] /= p->num_vertexs;
-    pt[ 1 ] /= p->num_vertexs;
-    pt[ 2 ] /= p->num_vertexs;
-    glVertex3fv ( pt );
+    pt[0] /= myPArray->num_vertexs;
+    pt[1] /= myPArray->num_vertexs;
+    pt[2] /= myPArray->num_vertexs;
+    glVertex3fv (pt);
   }
-}  
-
-/*----------------------------------------------------------------------*/
-static void draw_degenerates_quadrangles_as_points ( call_def_parray p ) { 
-
-  Tint       i, j, iv;
-  GLfloat    pt[ 3 ];
-  tel_point  pv = p -> vertices;
-
-#ifdef FULL_DEGENER
-  if ( g_fSkipRatio == 1. )
-    return;
-#endif
+}
 
-  if( p->num_edges > 0 ) {
-    for ( j=0 ; j<p->num_edges ; j+=4 ) {
-      pt[0] = pt[1] = pt[2] = 0.;
-      for ( i=0 ; i<4 ; i++ ) {
-        iv = p->edges[j+i];
-        pt[ 0 ] += pv[iv].xyz[ 0 ];
-        pt[ 1 ] += pv[iv].xyz[ 1 ];
-        pt[ 2 ] += pv[iv].xyz[ 2 ];
+// =======================================================================
+// function : DrawDegeneratesQuadranglesAsPoints
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawDegeneratesQuadranglesAsPoints() const
+{
+  Tint      i, j, iv;
+  GLfloat   pt[ 3 ];
+  tel_point pv = myPArray->vertices;
+
+  if (myPArray->num_edges > 0)
+  {
+    for (j = 0; j < myPArray->num_edges; j += 4)
+    {
+      pt[0] = pt[1] = pt[2] = 0.0;
+      for (i = 0; i < 4; ++i)
+      {
+        iv = myPArray->edges[j+i];
+        pt[0] += pv[iv].xyz[0];
+        pt[1] += pv[iv].xyz[1];
+        pt[2] += pv[iv].xyz[2];
       }
-      pt[ 0 ] /= 4;
-      pt[ 1 ] /= 4;
-      pt[ 2 ] /= 4;
+      pt[0] /= 4;
+      pt[1] /= 4;
+      pt[2] /= 4;
       glVertex3fv ( pt );
     }
-  } else {
-    for ( j=0 ; j<p->num_vertexs ; j+=4 ) {
-      pt[0] = pt[1] = pt[2] = 0.;
-      for ( i=0 ; i<4 ; i++ ) {
-        pt[ 0 ] += pv[j+i].xyz[ 0 ];
-        pt[ 1 ] += pv[j+i].xyz[ 1 ];
-        pt[ 2 ] += pv[j+i].xyz[ 2 ];
+  }
+  else
+  {
+    for (j = 0; j < myPArray->num_vertexs; j += 4)
+    {
+      pt[0] = pt[1] = pt[2] = 0.0;
+      for (i = 0; i < 4; ++i)
+      {
+        pt[0] += pv[j+i].xyz[0];
+        pt[1] += pv[j+i].xyz[1];
+        pt[2] += pv[j+i].xyz[2];
       }
-      pt[ 0 ] /= 4;
-      pt[ 1 ] /= 4;
-      pt[ 2 ] /= 4;
-      glVertex3fv ( pt );
+      pt[0] /= 4;
+      pt[1] /= 4;
+      pt[2] /= 4;
+      glVertex3fv (pt);
     }
   }
 }  
 
-/*----------------------------------------------------------------------*/
-static void draw_degenerates_quadranglestrips_as_points ( call_def_parray p ) { 
-
-  Tint       i, j, k, n;
-  GLfloat    pt[ 3 ];
-  tel_point  pv = p -> vertices;
-
-#ifdef FULL_DEGENER
-  if ( g_fSkipRatio == 1. )
-    return;
-#endif
-
-  if( p->num_bounds > 0 ) {
-    for ( k=n=0 ; k<p->num_bounds ; k++ ) {
-      for ( j=0 ; j<p->bounds[k]-2 ; j+=2 ) {
+// =======================================================================
+// function : DrawDegeneratesAsPoints
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawDegeneratesQuadranglestripsAsPoints() const
+{ 
+  Tint      i, j, k, n;
+  GLfloat   pt[3];
+  tel_point pv = myPArray->vertices;
+
+  if (myPArray->num_bounds > 0)
+  {
+    for (k = n = 0; k < myPArray->num_bounds; ++k)
+    {
+      for (j = 0; j < myPArray->bounds[k] - 2; j += 2)
+      {
         pt[0] = pt[1] = pt[2] = 0.;
-        for ( i=0 ; i<4 ; i++ ) {
-          pt[ 0 ] += pv[n+j+i].xyz[ 0 ];
-          pt[ 1 ] += pv[n+j+i].xyz[ 1 ];
-          pt[ 2 ] += pv[n+j+i].xyz[ 2 ];
+        for (i = 0; i < 4; ++i)
+        {
+          pt[0] += pv[n+j+i].xyz[0];
+          pt[1] += pv[n+j+i].xyz[1];
+          pt[2] += pv[n+j+i].xyz[2];
         }
-        pt[ 0 ] /= 4;
-        pt[ 1 ] /= 4;
-        pt[ 2 ] /= 4;
-        glVertex3fv ( pt );
+        pt[0] /= 4;
+        pt[1] /= 4;
+        pt[2] /= 4;
+        glVertex3fv (pt);
       }
-      n += p->bounds[k];
+      n += myPArray->bounds[k];
     }
-  } else {
-    for ( j=0 ; j<p->num_vertexs-2 ; j+=2 ) {
+  }
+  else
+  {
+    for (j = 0; j < myPArray->num_vertexs - 2; j += 2)
+    {
       pt[0] = pt[1] = pt[2] = 0.;
-      for ( i=0 ; i<4 ; i++ ) {
-        pt[ 0 ] += pv[j+i].xyz[ 0 ];
-        pt[ 1 ] += pv[j+i].xyz[ 1 ];
-        pt[ 2 ] += pv[j+i].xyz[ 2 ];
+      for (i = 0; i < 4; ++i)
+      {
+        pt[0] += pv[j+i].xyz[0];
+        pt[1] += pv[j+i].xyz[1];
+        pt[2] += pv[j+i].xyz[2];
       }
-      pt[ 0 ] /= 4;
-      pt[ 1 ] /= 4;
-      pt[ 2 ] /= 4;
-      glVertex3fv ( pt );
+      pt[0] /= 4;
+      pt[1] /= 4;
+      pt[2] /= 4;
+      glVertex3fv (pt);
     }
   }
-}  
+}
 
-/*----------------------------------------------------------------------*/
-static void draw_degenerates_as_points ( call_def_parray p, 
-                                        tel_colour edge_colour ) 
+// =======================================================================
+// function : DrawDegeneratesAsPoints
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawDegeneratesAsPoints (const TEL_COLOUR* theEdgeColour,
+                                                     const float       theSkipRatio) const
 {
+  if (theSkipRatio >= 1.0f)
+    return;
 
-  GLboolean zbuff_state = glIsEnabled(GL_DEPTH_TEST);
-  LightOff ();
-  if( zbuff_state ) glDisable(GL_DEPTH_TEST); 
-  glColor3fv( edge_colour->rgb );
-  glBegin ( GL_POINTS );
-  switch( draw_mode ) {
-      case GL_POINTS:
-        draw_degenerates_points_as_points( p );
-        break;
-      case GL_LINES:
-        draw_degenerates_lines_as_points( p );
-        break;
-      case GL_LINE_STRIP:
-      case GL_POLYGON:
-        draw_degenerates_polygons_as_points( p );
-        break;
-      case GL_TRIANGLES:
-        draw_degenerates_triangles_as_points( p );
-        break;
-      case GL_QUADS:
-        draw_degenerates_quadrangles_as_points( p );
-        break;
-      case GL_TRIANGLE_FAN:
-      case GL_TRIANGLE_STRIP:
-        draw_degenerates_trianglestrips_as_points( p );
-        break;
-      case GL_QUAD_STRIP:
-        draw_degenerates_quadranglestrips_as_points( p );
-        break;
-      default:
-        break;
+  GLboolean zbuff_state = glIsEnabled (GL_DEPTH_TEST);
+  glDisable (GL_LIGHTING);
+  if (zbuff_state)
+    glDisable (GL_DEPTH_TEST); 
+  glColor3fv (theEdgeColour->rgb);
+
+  glBegin (GL_POINTS);
+  switch (myDrawMode)
+  {
+    case GL_POINTS:
+      DrawDegeneratesPointsAsPoints();
+      break;
+    case GL_LINES:
+      DrawDegeneratesLinesAsPoints();
+      break;
+    case GL_LINE_STRIP:
+    case GL_POLYGON:
+      DrawDegeneratesPolygonsAsPoints();
+      break;
+    case GL_TRIANGLES:
+      DrawDegeneratesTrianglesAsPoints();
+      break;
+    case GL_QUADS:
+      DrawDegeneratesQuadranglesAsPoints();
+      break;
+    case GL_TRIANGLE_FAN:
+    case GL_TRIANGLE_STRIP:
+      DrawDegeneratesTrianglestripsAsPoints();
+      break;
+    case GL_QUAD_STRIP:
+      DrawDegeneratesQuadranglestripsAsPoints();
+      break;
+    default:
+      break;
   }
-
-  glEnd ();
-
-  if( zbuff_state ) glEnable(GL_DEPTH_TEST); 
+  glEnd();
+  if (zbuff_state)
+    glEnable (GL_DEPTH_TEST);
 }
 
-/*----------------------------------------------------------------------*/
-static void draw_degenerates_lines_as_lines ( call_def_parray p ) { 
-
-  Tint       i,j,n,iv;
-  tel_point  pv = p -> vertices;
+// =======================================================================
+// function : DrawDegeneratesLinesAsLines
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawDegeneratesLinesAsLines (const float theSkipRatio) const
+{
+  Tint i, iv;
+  tel_point  pv = myPArray->vertices;
 
-  n = p->num_vertexs;
-  j = (int)((1.-g_fSkipRatio)*n);
-  while ( j-- ) {
+  Tint n = myPArray->num_vertexs;
+  Tint j = int((1.0f - theSkipRatio) * n);
+  for (; j > 0; --j)
+  {
     i = OGL_Rand() % n;
-    p->keys[i] = -p->keys[i];
-  };
-
-  if( p->num_bounds > 0 ) {
-    if( p->num_edges > 0 ) {
-      for ( i=n=0 ; i<p->num_bounds ; i++ ) {
-        glBegin ( GL_LINES );
-        for ( j=0 ; j<p->bounds[i] ; j++ ) {
-          iv = p->edges[n+j];
-          if( p->keys[iv] < 0 ) {
-            p->keys[iv] = -p->keys[iv];
-            glVertex3fv ( pv[iv].xyz );
+    myPArray->keys[i] = -myPArray->keys[i];
+  }
+
+  if (myPArray->num_bounds > 0)
+  {
+    if (myPArray->num_edges > 0)
+    {
+      for (i = n = 0; i < myPArray->num_bounds; ++i)
+      {
+        glBegin (GL_LINES);
+        for (j = 0; j < myPArray->bounds[i]; ++j)
+        {
+          iv = myPArray->edges[n + j];
+          if (myPArray->keys[iv] < 0)
+          {
+            myPArray->keys[iv] = -myPArray->keys[iv];
+            glVertex3fv (pv[iv].xyz);
           }
         }
         glEnd();
-        n += p->bounds[i];
+        n += myPArray->bounds[i];
       }
-    } else {  
-      for ( i=n=0 ; i<p->num_bounds ; i++ ) {
-        glBegin ( GL_LINES );
-        for ( j=0 ; j<p->bounds[i] ; j++ ) {
-          if( p->keys[n+j] < 0 ) {
-            p->keys[n+j] = -p->keys[n+j];
-            glVertex3fv ( pv[n+j].xyz );
+    }
+    else
+    {
+      for (i = n = 0; i < myPArray->num_bounds; ++i)
+      {
+        glBegin (GL_LINES);
+        for (j = 0; j < myPArray->bounds[i]; ++j)
+        {
+          if (myPArray->keys[n+j] < 0)
+          {
+            myPArray->keys[n+j] = -myPArray->keys[n+j];
+            glVertex3fv (pv[n+j].xyz);
           }
         }
         glEnd();
-        n += p->bounds[i];
+        n += myPArray->bounds[i];
       }
     }
-  } else if( p->num_edges > 0 ) {
-    glBegin ( GL_LINES );
-    for ( j=0 ; j<p->num_edges ; j++ ) {
-      iv = p->edges[j];
-      if( p->keys[iv] < 0 ) {
-        p->keys[iv] = -p->keys[iv];
-        glVertex3fv ( pv[iv].xyz );
+  }
+  else if (myPArray->num_edges > 0)
+  {
+    glBegin (GL_LINES);
+    for (j = 0; j < myPArray->num_edges; ++j)
+    {
+      iv = myPArray->edges[j];
+      if (myPArray->keys[iv] < 0)
+      {
+        myPArray->keys[iv] = -myPArray->keys[iv];
+        glVertex3fv (pv[iv].xyz);
       }
     }
     glEnd();
-  } else {
-    glBegin ( GL_LINES );
-    for ( j=0 ; j<p->num_vertexs ; j++ ) {
-      if( p->keys[j] < 0 ) {
-        p->keys[j] = -p->keys[j];
-        glVertex3fv ( pv[j].xyz );
+  }
+  else
+  {
+    glBegin (GL_LINES);
+    for (j = 0; j < myPArray->num_vertexs; ++j)
+    {
+      if (myPArray->keys[j] < 0)
+      {
+        myPArray->keys[j] = -myPArray->keys[j];
+        glVertex3fv (pv[j].xyz);
       }
     }
     glEnd();
   }
-}  
+}
 
-/*----------------------------------------------------------------------*/
-static void draw_degenerates_triangles_as_lines ( call_def_parray p ) 
+// =======================================================================
+// function : DrawDegeneratesTrianglesAsLines
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawDegeneratesTrianglesAsLines (const float theSkipRatio) const
 { 
+  Tint i, iv;
+  tel_point pv = myPArray->vertices;
 
-  Tint       i,j,n,iv;
-  tel_point  pv = p -> vertices;
-
-  n = p->num_vertexs/3;
-  j = (int)((1.-g_fSkipRatio)*n);
-  while ( j-- ) {
+  Tint n = myPArray->num_vertexs / 3;
+  Tint j = int((1.0f - theSkipRatio) * n);
+  for (; j > 0; --j)
+  {
     i = OGL_Rand() % n; i *= 3;
-    p->keys[i] = -p->keys[i];
-  };
-
-  if( p->num_edges > 0 ) {
-    for ( j=0 ; j<p->num_edges ; j+=3 ) {
-      iv = p->edges[j];
-      if( p->keys[iv] < 0 ) { 
-        p->keys[iv] = -p->keys[iv];
-        glBegin ( GL_LINE_LOOP );
-        for ( i=0 ; i<3 ; i++ ) {
-          iv = p->edges[j+i];
-          glVertex3fv ( pv[iv].xyz );
+    myPArray->keys[i] = -myPArray->keys[i];
+  }
+
+  if (myPArray->num_edges > 0)
+  {
+    for (j = 0; j < myPArray->num_edges; j += 3)
+    {
+      iv = myPArray->edges[j];
+      if (myPArray->keys[iv] < 0)
+      { 
+        myPArray->keys[iv] = -myPArray->keys[iv];
+        glBegin (GL_LINE_LOOP);
+        for (i = 0; i < 3; ++i)
+        {
+          iv = myPArray->edges[j+i];
+          glVertex3fv (pv[iv].xyz);
         }
         glEnd();
       }
     }
-  } else {
-    for ( j=0 ; j<p->num_vertexs ; j+=3 ) {
-      if( p->keys[j] < 0 ) { 
-        p->keys[j] = -p->keys[j];
-        glBegin ( GL_LINE_LOOP );
-        for ( i=0 ; i<3 ; i++ ) {
-          glVertex3fv ( pv[j+i].xyz );
+  }
+  else
+  {
+    for (j = 0; j < myPArray->num_vertexs; j += 3)
+    {
+      if (myPArray->keys[j] < 0)
+      {
+        myPArray->keys[j] = -myPArray->keys[j];
+        glBegin (GL_LINE_LOOP);
+        for (i = 0; i < 3; ++i)
+        {
+          glVertex3fv (pv[j+i].xyz);
         }
         glEnd();
       }
     }
   }
-}  
+}
 
-/*----------------------------------------------------------------------*/
-static void draw_degenerates_trianglestrips_as_lines ( call_def_parray p ) 
+// =======================================================================
+// function : DrawDegeneratesTrianglesAsLines
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawDegeneratesTrianglestripsAsLines (const float theSkipRatio) const
 { 
-
-  Tint       i,j,k,n,ni;
-  tel_point  pv = p -> vertices;
-
-  if( p->num_bounds > 0 ) {
-    for ( i=n=0 ; i<p->num_bounds ; i++ ) {
-      ni = p->bounds[i]-2;
-      k = (int)((1.-g_fSkipRatio)*ni);
-      while ( k-- ) {
+  Tint i, j, k, n, ni;
+  tel_point pv = myPArray->vertices;
+
+  if (myPArray->num_bounds > 0)
+  {
+    for (i = n = 0; i < myPArray->num_bounds; ++i)
+    {
+      ni = myPArray->bounds[i] - 2;
+      k = int((1.0f - theSkipRatio) * ni);
+      for (; k > 0; --k)
+      {
         j = OGL_Rand() % ni; j += 2;
-        p->keys[n+j] = -p->keys[n+j];
-      };
-      for ( j=2 ; j<p->bounds[i] ; j++ ) {
-        if( p->keys[n+j] < 0 ) { 
-          p->keys[n+j] = -p->keys[n+j];
-          glBegin ( GL_LINE_LOOP );
-          glVertex3fv ( pv[n+j-2].xyz );
-          glVertex3fv ( pv[n+j-1].xyz );
-          glVertex3fv ( pv[n+j].xyz );
+        myPArray->keys[n+j] = -myPArray->keys[n+j];
+      }
+      for (j = 2; j < myPArray->bounds[i]; ++j)
+      {
+        if (myPArray->keys[n+j] < 0)
+        {
+          myPArray->keys[n+j] = -myPArray->keys[n+j];
+          glBegin (GL_LINE_LOOP);
+          glVertex3fv (pv[n+j-2].xyz);
+          glVertex3fv (pv[n+j-1].xyz);
+          glVertex3fv (pv[n+j].xyz);
           glEnd();
         }
       }
-      n += p->bounds[i];
+      n += myPArray->bounds[i];
     }
-  } else {
-    ni = p->num_vertexs-2;
-    k = (int)((1.-g_fSkipRatio)*ni);
-    while ( k-- ) {
+  }
+  else
+  {
+    ni = myPArray->num_vertexs - 2;
+    k = int((1.0f - theSkipRatio) * ni);
+    for (; k > 0; --k)
+    {
       j = OGL_Rand() % ni; j += 2;
-      p->keys[j] = -p->keys[j];
-    };
-    for ( j=2 ; j<p->num_vertexs ; j++ ) {
-      if( p->keys[j] < 0 ) { 
-        p->keys[j] = -p->keys[j];
-        glBegin ( GL_LINE_LOOP );
-        glVertex3fv ( pv[j-2].xyz );
-        glVertex3fv ( pv[j-1].xyz );
-        glVertex3fv ( pv[j].xyz );
+      myPArray->keys[j] = -myPArray->keys[j];
+    }
+    for (j = 2; j < myPArray->num_vertexs; ++j)
+    {
+      if (myPArray->keys[j] < 0)
+      {
+        myPArray->keys[j] = -myPArray->keys[j];
+        glBegin (GL_LINE_LOOP);
+        glVertex3fv (pv[j-2].xyz);
+        glVertex3fv (pv[j-1].xyz);
+        glVertex3fv (pv[j].xyz);
         glEnd();
       }
     }
   }
-}  
+}
 
-/*----------------------------------------------------------------------*/
-static void draw_degenerates_polygons_as_lines ( call_def_parray p )
+// =======================================================================
+// function : DrawDegeneratesPolygonsAsLines
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawDegeneratesPolygonsAsLines (const float theSkipRatio) const
 { 
-  Tint       i,j,n,iv;
-  tel_point  pv = p -> vertices;
+  Tint i, iv;
+  tel_point pv = myPArray->vertices;
 
-  n = p->num_vertexs;
-  j = (int)((1.-g_fSkipRatio)*n);
-  while ( j-- ) {
+  Tint n = myPArray->num_vertexs;
+  Tint j = int((1.0f - theSkipRatio) * n);
+  for (; j > 0; --j)
+  {
     i = OGL_Rand() % n;
-    p->keys[i] = -p->keys[i];
-  };
-
-  if( p->num_bounds > 0 ) {
-    if( p->num_edges > 0 ) {
-      for ( i=n=0 ; i<p->num_bounds ; i++ ) {
-        glBegin ( GL_LINE_LOOP );
-        for ( j=0 ; j<p->bounds[i] ; j++ ) {
-          iv = p->edges[n+j];
-          if( p->keys[iv] < 0 ) {
-            p->keys[iv] = -p->keys[iv];
-            glVertex3fv ( pv[iv].xyz );
+    myPArray->keys[i] = -myPArray->keys[i];
+  }
+
+  if (myPArray->num_bounds > 0)
+  {
+    if (myPArray->num_edges > 0)
+    {
+      for (i = n = 0; i < myPArray->num_bounds; ++i)
+      {
+        glBegin (GL_LINE_LOOP);
+        for (j = 0; j < myPArray->bounds[i]; ++j)
+        {
+          iv = myPArray->edges[n+j];
+          if (myPArray->keys[iv] < 0)
+          {
+            myPArray->keys[iv] = -myPArray->keys[iv];
+            glVertex3fv (pv[iv].xyz);
           }
         }
         glEnd();
-        n += p->bounds[i];
+        n += myPArray->bounds[i];
       }
-    } else {  
-      for ( i=n=0 ; i<p->num_bounds ; i++ ) {
-        glBegin ( GL_LINE_LOOP );
-        for ( j=0 ; j<p->bounds[i] ; j++ ) {
-          if( p->keys[n+j] < 0 ) {
-            p->keys[n+j] = -p->keys[n+j];
-            glVertex3fv ( pv[n+j].xyz );
+    }
+    else
+    {
+      for (i = n = 0; i < myPArray->num_bounds; ++i)
+      {
+        glBegin (GL_LINE_LOOP);
+        for (j = 0; j < myPArray->bounds[i]; ++j)
+        {
+          if (myPArray->keys[n+j] < 0)
+          {
+            myPArray->keys[n+j] = -myPArray->keys[n+j];
+            glVertex3fv (pv[n+j].xyz);
           }
         }
         glEnd();
-        n += p->bounds[i];
+        n += myPArray->bounds[i];
       }
     }
-  } else if( p->num_edges > 0 ) {
-    glBegin ( GL_LINE_LOOP );
-    for ( j=0 ; j<p->num_edges ; j++ ) {
-      iv = p->edges[j];
-      if( p->keys[iv] < 0 ) {
-        p->keys[iv] = -p->keys[iv];
-        glVertex3fv ( pv[iv].xyz );
+  }
+  else if (myPArray->num_edges > 0)
+  {
+    glBegin (GL_LINE_LOOP);
+    for (j = 0; j < myPArray->num_edges; ++j)
+    {
+      iv = myPArray->edges[j];
+      if (myPArray->keys[iv] < 0)
+      {
+        myPArray->keys[iv] = -myPArray->keys[iv];
+        glVertex3fv (pv[iv].xyz);
       }
     }
     glEnd();
-  } else {
-    glBegin ( GL_LINE_LOOP );
-    for ( j=0 ; j<p->num_vertexs ; j++ ) {
-      if( p->keys[j] < 0 ) {
-        p->keys[j] = -p->keys[j];
-        glVertex3fv ( pv[j].xyz );
+  }
+  else
+  {
+    glBegin (GL_LINE_LOOP);
+    for (j = 0; j < myPArray->num_vertexs; ++j)
+    {
+      if (myPArray->keys[j] < 0)
+      {
+        myPArray->keys[j] = -myPArray->keys[j];
+        glVertex3fv (pv[j].xyz);
       }
     }
     glEnd();
   }
-
 }  
 
-/*----------------------------------------------------------------------*/
-static void draw_degenerates_quadrangles_as_lines ( call_def_parray p ) 
-{ 
-
-  Tint       i,j,n,iv;
-  tel_point  pv = p -> vertices;
+// =======================================================================
+// function : DrawDegeneratesQuadranglesAsLines
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawDegeneratesQuadranglesAsLines (const float theSkipRatio) const
+{
+  Tint i, iv;
+  tel_point pv = myPArray->vertices;
 
-  n = p->num_vertexs/4;
-  j = (int)((1.-g_fSkipRatio)*n);
-  while ( j-- ) {
+  Tint n = myPArray->num_vertexs / 4;
+  Tint j = int((1.0f - theSkipRatio) * n);
+  for (; j > 0; --j)
+  {
     i = OGL_Rand() % n; i *= 4;
-    p->keys[i] = -p->keys[i];
-  };
-
-  if( p->num_edges > 0 ) {
-    for ( j=0 ; j<p->num_edges ; j+=4 ) {
-      iv = p->edges[j];
-      if( p->keys[iv] < 0 ) {
-        p->keys[iv] = -p->keys[iv];
-        glBegin ( GL_LINE_LOOP );
-        for ( i=0 ; i<4 ; i++ ) {
-          iv = p->edges[j+i];
-          glVertex3fv ( pv[iv].xyz );
+    myPArray->keys[i] = -myPArray->keys[i];
+  }
+
+  if (myPArray->num_edges > 0)
+  {
+    for (j = 0; j < myPArray->num_edges; j += 4)
+    {
+      iv = myPArray->edges[j];
+      if (myPArray->keys[iv] < 0)
+      {
+        myPArray->keys[iv] = -myPArray->keys[iv];
+        glBegin (GL_LINE_LOOP);
+        for (i = 0; i < 4; ++i)
+        {
+          iv = myPArray->edges[j+i];
+          glVertex3fv (pv[iv].xyz);
         }
         glEnd();
       }
     }
-  } else {
-    for ( j=0 ; j<p->num_vertexs ; j+=4 ) {
-      if( p->keys[j] < 0 ) {
-        p->keys[j] = -p->keys[j];
-        glBegin ( GL_LINE_LOOP );
-        for ( i=0 ; i<4 ; i++ ) {
-          glVertex3fv ( pv[j+i].xyz );
+  }
+  else
+  {
+    for (j = 0; j < myPArray->num_vertexs; j += 4)
+    {
+      if (myPArray->keys[j] < 0)
+      {
+        myPArray->keys[j] = -myPArray->keys[j];
+        glBegin (GL_LINE_LOOP);
+        for (i = 0; i < 4; ++i)
+        {
+          glVertex3fv (pv[j+i].xyz);
         }
         glEnd();
       }
     }
   }
-}  
+}
 
-/*----------------------------------------------------------------------*/
-static void draw_degenerates_quadranglestrips_as_lines ( call_def_parray p )
+// =======================================================================
+// function : DrawDegeneratesQuadranglesAsLines
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawDegeneratesQuadranglestripsAsLines (const float theSkipRatio) const
 { 
-
-  Tint       i,j,k,n,ni;
-  tel_point  pv = p -> vertices;
-
-  if( p->num_bounds > 0 ) {
-    for ( i=n=0 ; i<p->num_bounds ; i++ ) {
-      ni = p->bounds[i]/2-2;
-      k = (int)((1.-g_fSkipRatio)*ni);
-      while ( k-- ) {
-        j = OGL_Rand() % ni; j = j*2+2;
-        p->keys[n+j] = -p->keys[n+j];
-      };
-      for ( j=3 ; j<p->bounds[i] ; j+=2 ) {
-        if( p->keys[n+j] < 0 ) {
-          p->keys[n+j] = -p->keys[n+j];
-          glBegin ( GL_LINE_LOOP );
-          glVertex3fv ( pv[n+j-3].xyz );
-          glVertex3fv ( pv[n+j-2].xyz );
-          glVertex3fv ( pv[n+j-1].xyz );
-          glVertex3fv ( pv[n+j].xyz );
+  Tint i, j, k, n, ni;
+  tel_point pv = myPArray->vertices;
+
+  if (myPArray->num_bounds > 0)
+  {
+    for (i = n = 0; i < myPArray->num_bounds; ++i)
+    {
+      ni = myPArray->bounds[i] / 2 - 2;
+      k = int((1.0f - theSkipRatio) * ni);
+      for (; k > 0; --k)
+      {
+        j = OGL_Rand() % ni; j = j * 2 + 2;
+        myPArray->keys[n+j] = -myPArray->keys[n+j];
+      }
+      for (j = 3; j < myPArray->bounds[i]; j += 2)
+      {
+        if (myPArray->keys[n+j] < 0)
+        {
+          myPArray->keys[n+j] = -myPArray->keys[n+j];
+          glBegin (GL_LINE_LOOP);
+          glVertex3fv (pv[n+j-3].xyz);
+          glVertex3fv (pv[n+j-2].xyz);
+          glVertex3fv (pv[n+j-1].xyz);
+          glVertex3fv (pv[n+j].xyz);
           glEnd();
         }
       }
-      n += p->bounds[i];
+      n += myPArray->bounds[i];
+    }
+  }
+  else
+  {
+    ni = myPArray->num_vertexs / 2 - 2;
+    k = int((1.0f - theSkipRatio) * ni);
+    for (; k > 0; --k)
+    {
+      j = OGL_Rand() % ni; j = j * 2 + 2;
+      myPArray->keys[j] = -myPArray->keys[j];
     }
-  } else {
-    ni = p->num_vertexs/2-2;
-    k = (int)((1.-g_fSkipRatio)*ni);
-    while ( k-- ) {
-      j = OGL_Rand() % ni; j = j*2+2;
-      p->keys[j] = -p->keys[j];
-    };
-    for ( j=3 ; j<p->num_vertexs ; j+=2 ) {
-      if( p->keys[j] < 0 ) {
-        p->keys[j] = -p->keys[j];
-        glBegin ( GL_LINE_LOOP );
-        glVertex3fv ( pv[j-3].xyz );
-        glVertex3fv ( pv[j-2].xyz );
-        glVertex3fv ( pv[j-1].xyz );
-        glVertex3fv ( pv[j].xyz );
+    for (j = 3; j < myPArray->num_vertexs; j += 2)
+    {
+      if (myPArray->keys[j] < 0)
+      {
+        myPArray->keys[j] = -myPArray->keys[j];
+        glBegin (GL_LINE_LOOP);
+        glVertex3fv (pv[j-3].xyz);
+        glVertex3fv (pv[j-2].xyz);
+        glVertex3fv (pv[j-1].xyz);
+        glVertex3fv (pv[j].xyz);
         glEnd();
       }
     }
   }
-}  
+}
 
-/*----------------------------------------------------------------------*/
-static void draw_degenerates_as_lines ( call_def_parray p, 
-                                       tel_colour edge_colour )
+// =======================================================================
+// function : DrawDegeneratesAsLines
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawDegeneratesAsLines (const TEL_COLOUR*               theEdgeColour,
+                                                    const Handle(OpenGl_Workspace)& theWorkspace) const
 {
+  const float aSkipRatio = theWorkspace->SkipRatio;
 
-  GLint renderMode;
-
-  GLboolean zbuff_state = glIsEnabled(GL_DEPTH_TEST);
+  GLboolean zbuff_state = glIsEnabled (GL_DEPTH_TEST);
 
-  LightOff ();
+  glDisable (GL_LIGHTING);
 
-  if( zbuff_state ) glDisable(GL_DEPTH_TEST); 
+  if (zbuff_state)
+    glDisable (GL_DEPTH_TEST); 
 
-  glColor3fv( edge_colour->rgb );
+  glColor3fv (theEdgeColour->rgb);
 
-  if( g_fSkipRatio != 0 ) switch( draw_mode ) {
+  if (aSkipRatio != 0.0f)
+  {
+    switch (myDrawMode)
+    {
       case GL_POINTS:
-        draw_degenerates_points_as_points( p );
+        if (aSkipRatio < 1.0f)
+          DrawDegeneratesPointsAsPoints();
         break;
       case GL_LINES:
-        draw_degenerates_lines_as_lines( p );
+        DrawDegeneratesLinesAsLines (aSkipRatio);
         break;
       case GL_LINE_STRIP:
       case GL_POLYGON:
-        draw_degenerates_polygons_as_lines( p );
+        DrawDegeneratesPolygonsAsLines (aSkipRatio);
         break;
       case GL_TRIANGLES:
-        draw_degenerates_triangles_as_lines( p );
+        DrawDegeneratesTrianglesAsLines (aSkipRatio);
         break;
       case GL_QUADS:
-        draw_degenerates_quadrangles_as_lines( p );
+        DrawDegeneratesQuadranglesAsLines (aSkipRatio);
         break;
       case GL_TRIANGLE_FAN:
       case GL_TRIANGLE_STRIP:
-        draw_degenerates_trianglestrips_as_lines( p );
+        DrawDegeneratesTrianglestripsAsLines (aSkipRatio);
         break;
       case GL_QUAD_STRIP:
-        draw_degenerates_quadranglestrips_as_lines( p );
+        DrawDegeneratesQuadranglestripsAsLines (aSkipRatio);
         break;
       default:
         break;
+    }
   }
-  else {
+  else
+  {
     int i,n;
-
-#ifdef OCC3192
-    GLboolean color_array_mode, 
-      edge_flag_array_mode,
-      index_array_mode,
-      normal_array_mode,
-      texture_coord_array_mode,
-      vertex_array_mode;
-#endif
-    glPushAttrib( GL_POLYGON_BIT );
-    glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
-
-#ifdef OCC3192
-    color_array_mode         = glIsEnabled( GL_COLOR_ARRAY );
-    edge_flag_array_mode     = glIsEnabled( GL_EDGE_FLAG_ARRAY );
-    index_array_mode         = glIsEnabled( GL_INDEX_ARRAY );
-    normal_array_mode        = glIsEnabled( GL_NORMAL_ARRAY );
-    texture_coord_array_mode = glIsEnabled( GL_TEXTURE_COORD_ARRAY );
-    vertex_array_mode        = glIsEnabled( GL_VERTEX_ARRAY );
-
-    glDisableClientState( GL_COLOR_ARRAY );
-    glDisableClientState( GL_EDGE_FLAG_ARRAY );
-    glDisableClientState( GL_INDEX_ARRAY );
-    glDisableClientState( GL_NORMAL_ARRAY );
-    glDisableClientState( GL_TEXTURE_COORD_ARRAY );
-
-    if( !vertex_array_mode ) glEnableClientState( GL_VERTEX_ARRAY );
-#else
-    glEnableClientState( GL_VERTEX_ARRAY );
-#endif
-    glVertexPointer(3, GL_FLOAT, 0, p->vertices); /* array of vertices  */
-
-    glGetIntegerv( GL_RENDER_MODE, &renderMode );
-
-    if( p->num_bounds > 0 ) {
-      if( p->num_edges > 0 ) {
-        for( i=n=0 ; i<p->num_bounds ; i++ ) {
-          if( renderMode == GL_FEEDBACK )
-            draw_primitive_elements( p, draw_mode, p->bounds[i], 
-            GL_UNSIGNED_INT, (GLenum*) &p->edges[n]);
-          else
-            glDrawElements( draw_mode, p->bounds[i],
-            GL_UNSIGNED_INT, &p->edges[n]);
-          n += p->bounds[i];
-        }
-      } else {
-        for( i=n=0 ; i<p->num_bounds ; i++ ) {
-          if( renderMode == GL_FEEDBACK )
-            draw_primitive_array( p, draw_mode, n, p->bounds[i]);
-          else
-            glDrawArrays( draw_mode, n, p->bounds[i]);
-          n += p->bounds[i];
+    glPushAttrib (GL_POLYGON_BIT);
+    glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+
+    GLboolean color_array_mode         = glIsEnabled (GL_COLOR_ARRAY);
+    GLboolean edge_flag_array_mode     = glIsEnabled (GL_EDGE_FLAG_ARRAY);
+    GLboolean index_array_mode         = glIsEnabled (GL_INDEX_ARRAY);
+    GLboolean normal_array_mode        = glIsEnabled (GL_NORMAL_ARRAY);
+    GLboolean texture_coord_array_mode = glIsEnabled (GL_TEXTURE_COORD_ARRAY);
+    GLboolean vertex_array_mode        = glIsEnabled (GL_VERTEX_ARRAY);
+
+    glDisableClientState (GL_COLOR_ARRAY);
+    glDisableClientState (GL_EDGE_FLAG_ARRAY);
+    glDisableClientState (GL_INDEX_ARRAY);
+    glDisableClientState (GL_NORMAL_ARRAY);
+    glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+
+    if (!vertex_array_mode)
+      glEnableClientState (GL_VERTEX_ARRAY);
+
+    glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices
+
+    GLint renderMode;
+    glGetIntegerv (GL_RENDER_MODE, &renderMode);
+
+    if (myPArray->num_bounds > 0)
+    {
+      if (myPArray->num_edges > 0)
+      {
+        for (i = n = 0; i < myPArray->num_bounds; ++i)
+        {
+          DrawElements (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
+                        myPArray->bounds[i], (GLenum* )&myPArray->edges[n]);
+          n += myPArray->bounds[i];
         }
       }
-    } else if( p->num_edges > 0 ) {
-      if( renderMode == GL_FEEDBACK )
-        draw_primitive_elements( p, draw_mode, p->num_edges, 
-        GL_UNSIGNED_INT, (GLenum*) p->edges);
-      else
-        glDrawElements( draw_mode, p->num_edges,
-        GL_UNSIGNED_INT, p->edges);
-    } else {
-      if( renderMode == GL_FEEDBACK )
-        draw_primitive_array( p, draw_mode, 0, p->num_vertexs);
       else
-        glDrawArrays( draw_mode, 0, p->num_vertexs);
+      {
+        for (i = n = 0; i < myPArray->num_bounds; ++i)
+        {
+          DrawArrays (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
+                      n, myPArray->bounds[i]);
+          n += myPArray->bounds[i];
+        }
+      }
+    }
+    else if (myPArray->num_edges > 0)
+    {
+      DrawElements (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
+                    myPArray->num_edges, (GLenum* )myPArray->edges);
+    }
+    else
+    {
+      DrawArrays (theWorkspace, myPArray, (renderMode == GL_FEEDBACK), myDrawMode,
+                  0, myPArray->num_vertexs);
     }
 
-#ifdef OCC3192
-    if( !vertex_array_mode ) glDisableClientState( GL_VERTEX_ARRAY );
+    if (!vertex_array_mode) glDisableClientState (GL_VERTEX_ARRAY);
+
+    if (color_array_mode)         glEnableClientState (GL_COLOR_ARRAY);
+    if (edge_flag_array_mode)     glEnableClientState (GL_EDGE_FLAG_ARRAY);
+    if (index_array_mode)         glEnableClientState (GL_INDEX_ARRAY);
+    if (normal_array_mode)        glEnableClientState (GL_NORMAL_ARRAY);
+    if (texture_coord_array_mode) glEnableClientState (GL_TEXTURE_COORD_ARRAY);
 
-    if( color_array_mode )         glEnableClientState( GL_COLOR_ARRAY );
-    if( edge_flag_array_mode )     glEnableClientState( GL_EDGE_FLAG_ARRAY );
-    if( index_array_mode )         glEnableClientState( GL_INDEX_ARRAY );
-    if( normal_array_mode )        glEnableClientState( GL_NORMAL_ARRAY );
-    if( texture_coord_array_mode ) glEnableClientState( GL_TEXTURE_COORD_ARRAY );
-#endif
     glPopAttrib();
   }
 
-  if( zbuff_state ) glEnable(GL_DEPTH_TEST); 
-
+  if (zbuff_state)
+    glEnable(GL_DEPTH_TEST); 
 }  
 
-static void draw_degenerates_as_bboxs ( call_def_parray p, 
-                                        tel_colour edge_colour )
+// =======================================================================
+// function : DrawDegeneratesAsBBoxs
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::DrawDegeneratesAsBBoxs (const TEL_COLOUR* theEdgeColour) const
 {
+  GLfloat minp[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
+  GLfloat maxp[3] = { FLT_MIN, FLT_MIN, FLT_MIN };
+  tel_point pv = myPArray->vertices;
+
+  glDisable (GL_LIGHTING);
+
+  glColor3fv (theEdgeColour->rgb);
+
+  for (Tint i = 0; i < myPArray->num_vertexs; ++i)
+  {
+    if (pv[i].xyz[0] < minp[0])
+      minp[0] = pv[i].xyz[0];
+    if (pv[i].xyz[1] < minp[1])
+      minp[1] = pv[i].xyz[1];
+    if (pv[i].xyz[2] < minp[2])
+      minp[2] = pv[i].xyz[2];
+
+    if (pv[i].xyz[0] > maxp[0])
+      maxp[0] = pv[i].xyz[0];
+    if (pv[i].xyz[1] > maxp[1])
+      maxp[1] = pv[i].xyz[1];
+    if (pv[i].xyz[2] > maxp[2])
+      maxp[2] = pv[i].xyz[2];
+  }
+
+  glBegin (GL_LINE_STRIP);
+
+  glVertex3fv (minp);
+  glVertex3f (minp[0], maxp[1], minp[2]);
+  glVertex3f (minp[0], maxp[1], maxp[2]);
+  glVertex3f (minp[0], minp[1], maxp[2]);
+  glVertex3f (minp[0], minp[1], minp[2]);
+
+  glVertex3f (maxp[0], minp[1], minp[2]);
+  glVertex3f (maxp[0], maxp[1], minp[2]);
+  glVertex3f (maxp[0], maxp[1], maxp[2]);
+  glVertex3f (maxp[0], minp[1], maxp[2]);
+  glVertex3f (maxp[0], minp[1], minp[2]);
 
-  Tint      i;
-  GLfloat   minp[ 3 ] = { FLT_MAX, FLT_MAX, FLT_MAX };
-  GLfloat   maxp[ 3 ] = { FLT_MIN, FLT_MIN, FLT_MIN };
-  tel_point pv = p -> vertices;
-
-  LightOff ();
-
-  glColor3fv( edge_colour->rgb );
-
-  for ( i=0 ; i<p->num_vertexs ; ++i ) {
-    if ( pv[  i  ].xyz[ 0 ] < minp[ 0 ] )
-      minp[ 0 ] = pv[  i  ].xyz[ 0 ] ;
-    if ( pv[  i  ].xyz[ 1 ] < minp[ 1 ] )
-      minp[ 1 ] = pv[  i  ].xyz[ 1 ] ;
-    if ( pv[  i  ].xyz[ 2 ] < minp[ 2 ] )
-      minp[ 2 ] = pv[  i  ].xyz[ 2 ] ;
-
-    if ( pv[  i  ].xyz[ 0 ] > maxp[ 0 ] )
-      maxp[ 0 ] = pv[  i  ].xyz[ 0 ] ;
-    if ( pv[  i  ].xyz[ 1 ] > maxp[ 1 ] )
-      maxp[ 1 ] = pv[  i  ].xyz[ 1 ] ;
-    if ( pv[  i ].xyz[ 2 ] > maxp[ 2 ] )
-      maxp[ 2 ] = pv[  i  ].xyz[ 2 ] ;
-  }  /* end for ( i ) */
-
-  glBegin ( GL_LINE_STRIP );
-
-  glVertex3fv ( minp );
-  glVertex3f ( minp[ 0 ], maxp[ 1 ], minp[ 2 ] );
-  glVertex3f ( minp[ 0 ], maxp[ 1 ], maxp[ 2 ] );
-  glVertex3f ( minp[ 0 ], minp[ 1 ], maxp[ 2 ] );
-  glVertex3f ( minp[ 0 ], minp[ 1 ], minp[ 2 ] );
-
-  glVertex3f ( maxp[ 0 ], minp[ 1 ], minp[ 2 ] );
-  glVertex3f ( maxp[ 0 ], maxp[ 1 ], minp[ 2 ] );
-  glVertex3f ( maxp[ 0 ], maxp[ 1 ], maxp[ 2 ] );
-  glVertex3f ( maxp[ 0 ], minp[ 1 ], maxp[ 2 ] );
-  glVertex3f ( maxp[ 0 ], minp[ 1 ], minp[ 2 ] );
-
-  glVertex3f ( maxp[ 0 ], minp[ 1 ], maxp[ 2 ] );
-  glVertex3f ( minp[ 0 ], minp[ 1 ], maxp[ 2 ] );
-  glVertex3f ( minp[ 0 ], maxp[ 1 ], maxp[ 2 ] );
-  glVertex3fv ( maxp );
-  glVertex3f ( maxp[ 0 ], maxp[ 1 ], minp[ 2 ] );
-  glVertex3f ( minp[ 0 ], maxp[ 1 ], minp[ 2 ] );
+  glVertex3f (maxp[0], minp[1], maxp[2]);
+  glVertex3f (minp[0], minp[1], maxp[2]);
+  glVertex3f (minp[0], maxp[1], maxp[2]);
+  glVertex3fv (maxp);
+  glVertex3f (maxp[0], maxp[1], minp[2]);
+  glVertex3f (minp[0], maxp[1], minp[2]);
 
   glEnd();
+}
 
-}  /* end draw_degenerates_as_bboxs */
+// =======================================================================
+// function : OpenGl_PrimitiveArray
+// purpose  :
+// =======================================================================
+OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (CALL_DEF_PARRAY* thePArray)
+: myPArray (thePArray),
+  myDrawMode (GL_NONE)
+{
+  switch (myPArray->type)
+  {
+    case TelPointsArrayType:
+      myDrawMode = GL_POINTS;
+      break;
+    case TelPolylinesArrayType:
+      myDrawMode = GL_LINE_STRIP;
+      break;
+    case TelSegmentsArrayType:
+      myDrawMode = GL_LINES;
+      break;
+    case TelPolygonsArrayType:
+      myDrawMode = GL_POLYGON;
+      break;
+    case TelTrianglesArrayType:
+      myDrawMode = GL_TRIANGLES;
+      break;
+    case TelQuadranglesArrayType:
+      myDrawMode = GL_QUADS;
+      break;
+    case TelTriangleStripsArrayType:
+      myDrawMode = GL_TRIANGLE_STRIP;
+      break;
+    case TelQuadrangleStripsArrayType:
+      myDrawMode = GL_QUAD_STRIP;
+      break;
+    case TelTriangleFansArrayType:
+      myDrawMode = GL_TRIANGLE_FAN;
+      break;
+  }
+}
+
+// =======================================================================
+// function : ~OpenGl_PrimitiveArray
+// purpose  :
+// =======================================================================
+OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray ()
+{
+  if (myPArray == NULL)
+    return;
+
+  if (myPArray->VBOEnabled == VBO_OK)
+  {
+    OpenGl_ResourceCleaner* aResCleaner = OpenGl_ResourceCleaner::GetInstance();
+    if (myPArray->bufferVBO[VBOEdges] != 0)
+      aResCleaner->AddResource ((GLCONTEXT )myPArray->contextId,
+                                new OpenGl_ResourceVBO (myPArray->bufferVBO[VBOEdges]));
+    if (myPArray->bufferVBO[VBOVertices] != 0)
+      aResCleaner->AddResource ((GLCONTEXT )myPArray->contextId,
+                                new OpenGl_ResourceVBO (myPArray->bufferVBO[VBOVertices]));
+    if (myPArray->bufferVBO[VBOVcolours] != 0)
+      aResCleaner->AddResource ((GLCONTEXT )myPArray->contextId,
+                                new OpenGl_ResourceVBO (myPArray->bufferVBO[VBOVcolours]));
+    if (myPArray->bufferVBO[VBOVnormals] != 0)
+      aResCleaner->AddResource ((GLCONTEXT )myPArray->contextId,
+                                new OpenGl_ResourceVBO (myPArray->bufferVBO[VBOVnormals]));
+    if (myPArray->bufferVBO[VBOVtexels] != 0)
+      aResCleaner->AddResource ((GLCONTEXT )myPArray->contextId,
+                                new OpenGl_ResourceVBO (myPArray->bufferVBO[VBOVtexels]));
+  }
+}
+
+// =======================================================================
+// function : Render
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
+{
+  if (myPArray == NULL || myDrawMode == GL_NONE)
+    return;
+
+  // create VBOs on first render call
+  if (myPArray->VBOEnabled == -1) // special value for uninitialized state
+  {
+    myPArray->VBOEnabled = OpenGl_GraphicDriver::ToUseVBO() && (theWorkspace->GetGlContext()->arbVBO != NULL);
+    if (myPArray->VBOEnabled != 0)
+      BuildVBO (theWorkspace);
+  }
+
+  switch (myPArray->type)
+  {
+    case TelPointsArrayType:
+    case TelPolylinesArrayType:
+    case TelSegmentsArrayType:
+    {
+      glDisable (GL_LIGHTING);
+
+      if ((theWorkspace->NamedStatus & OPENGL_NS_ANIMATION) != 0 &&
+          (theWorkspace->NamedStatus & OPENGL_NS_WIREFRAME) == 0 &&
+           theWorkspace->DegenerateModel)
+      {
+        glDisable (GL_DEPTH_TEST);
+        if (theWorkspace->NamedStatus & OPENGL_NS_TEXTURE)
+          DisableTexture();
+        theWorkspace->NamedStatus |= OPENGL_NS_WIREFRAME;
+      }
+      break;
+    }
+    case TelPolygonsArrayType:
+    case TelTrianglesArrayType:
+    case TelQuadranglesArrayType:
+    case TelTriangleStripsArrayType:
+    case TelTriangleFansArrayType:
+    case TelQuadrangleStripsArrayType:
+    {
+      if ((theWorkspace->NamedStatus & OPENGL_NS_ANIMATION) != 0 &&
+          (theWorkspace->NamedStatus & OPENGL_NS_WIREFRAME) != 0 &&
+           theWorkspace->DegenerateModel < 2)
+      {
+        if (theWorkspace->NamedStatus & OPENGL_NS_TEXTURE)
+          EnableTexture();
+        glEnable (GL_DEPTH_TEST);
+        theWorkspace->NamedStatus &= ~OPENGL_NS_WIREFRAME;
+      }
+      break;
+    }
+    default:
+      break;
+  }
+
+  const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace (Standard_True);
+  const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True);
+
+  Tint aFrontLightingModel = anAspectFace->Context().IntFront.color_mask;
+  const TEL_COLOUR* anInteriorColor = &anAspectFace->Context().IntFront.matcol;
+  const TEL_COLOUR* anEdgeColor = &anAspectFace->AspectEdge()->Color();
+  const TEL_COLOUR* aLineColor = &anAspectLine->Color();
+
+  // Use highlight colors
+  if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
+  {                         
+    anEdgeColor = anInteriorColor = aLineColor = theWorkspace->HighlightColor;
+    aFrontLightingModel = 0;
+  }
+
+  DrawArray (aFrontLightingModel,
+             anAspectFace->Context().InteriorStyle,
+             anAspectFace->Context().Edge,
+             anInteriorColor,
+             aLineColor,
+             anEdgeColor,
+             &anAspectFace->Context().IntFront,
+             theWorkspace);
+
+  switch (myPArray->type)
+  {
+    case TelPointsArrayType:
+    case TelPolylinesArrayType:
+    case TelSegmentsArrayType:
+    {
+      if (theWorkspace->NamedStatus & OPENGL_NS_TEXTURE)
+        EnableTexture();
+    }
+  }
+}