0023428: Extend OpenGl_Context to use Geometry Shaders extension
[occt.git] / src / OpenGl / OpenGl_Group.cxx
1 // Created on: 2011-08-01
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 #include <OpenGl_Group.hxx>
22
23 #include <OpenGl_TextureBox.hxx>
24 #include <OpenGl_PrimitiveArray.hxx>
25
26 /*----------------------------------------------------------------------*/
27
28 OpenGl_Group::OpenGl_Group ()
29 : myAspectLine(NULL),
30   myAspectFace(NULL),
31   myAspectMarker(NULL),
32   myAspectText(NULL),
33   myFirst(NULL), myLast(NULL)
34 {
35 }
36
37 OpenGl_Group::~OpenGl_Group()
38 {
39   Release (Handle(OpenGl_Context)());
40 }
41
42 /*----------------------------------------------------------------------*/
43
44 void OpenGl_Group::SetAspectLine (const CALL_DEF_CONTEXTLINE& theContext,
45                                   const Standard_Boolean theIsGlobal)
46 {
47   if (theIsGlobal || myFirst == NULL)
48   {
49     if (myAspectLine == NULL)
50       myAspectLine = new OpenGl_AspectLine();
51     myAspectLine->SetContext (theContext);
52   }
53   else
54   {
55     OpenGl_AspectLine* anAspectLine = new OpenGl_AspectLine();
56     anAspectLine->SetContext (theContext);
57     AddElement (TelNil/*TelAspectLine*/, anAspectLine);
58   }
59 }
60
61 /*----------------------------------------------------------------------*/
62
63 void OpenGl_Group::SetAspectFace (const CALL_DEF_CONTEXTFILLAREA& theContext,
64                                   const Standard_Boolean theIsGlobal)
65 {
66   if (theIsGlobal || myFirst == NULL)
67   {
68     if (myAspectFace == NULL)
69       myAspectFace = new OpenGl_AspectFace();
70     myAspectFace->SetContext (theContext);
71   }
72   else
73   {
74     OpenGl_AspectFace* anAspectFace = new OpenGl_AspectFace();
75     anAspectFace->SetContext (theContext);
76     AddElement (TelNil/*TelAspectFace*/, anAspectFace);
77   }
78 }
79
80 /*----------------------------------------------------------------------*/
81
82 void OpenGl_Group::SetAspectMarker (const CALL_DEF_CONTEXTMARKER& theContext,
83                                     const Standard_Boolean theIsGlobal)
84 {
85   if (theIsGlobal || myFirst == NULL)
86   {
87     if (myAspectMarker == NULL)
88       myAspectMarker = new OpenGl_AspectMarker();
89     myAspectMarker->SetContext (theContext);
90   }
91   else
92   {
93     OpenGl_AspectMarker* anAspectMarker = new OpenGl_AspectMarker();
94     anAspectMarker->SetContext (theContext);
95     AddElement (TelNil/*TelAspectMarker*/, anAspectMarker);
96   }
97 }
98
99 /*----------------------------------------------------------------------*/
100
101 void OpenGl_Group::SetAspectText (const CALL_DEF_CONTEXTTEXT& theContext,
102                                   const Standard_Boolean theIsGlobal)
103 {
104   if (theIsGlobal || myFirst == NULL)
105   {
106     if (myAspectText == NULL)
107       myAspectText = new OpenGl_AspectText();
108     myAspectText->SetContext (theContext);
109   }
110   else
111   {
112     OpenGl_AspectText* anAspectText = new OpenGl_AspectText();
113     anAspectText->SetContext (theContext);
114     AddElement ( TelNil/*TelAspectText*/, anAspectText);
115   }
116 }
117
118 /*----------------------------------------------------------------------*/
119
120 void OpenGl_Group::AddElement (const TelType AType, OpenGl_Element *AElem )
121 {
122   OpenGl_ElementNode *node = new OpenGl_ElementNode();
123
124   node->type = AType;
125   node->elem = AElem;
126   node->next = NULL;
127   (myLast? myLast->next : myFirst) = node;
128   myLast = node;
129 }
130
131 /*----------------------------------------------------------------------*/
132
133 void OpenGl_Group::RemovePrimitiveArray (const Handle(OpenGl_Context)& theGlCtx,
134                                          CALL_DEF_PARRAY*              thePArray)
135 {
136   OpenGl_ElementNode *prevnode = NULL, *node = myFirst;
137   while (node != NULL)
138   {
139     if (node->type == TelParray)
140     {
141       CALL_DEF_PARRAY* aCurPArray = ((const OpenGl_PrimitiveArray* )node->elem)->PArray();
142
143       // validate for correct pointer
144       if (aCurPArray->num_bounds  == thePArray->num_bounds  && 
145           aCurPArray->num_edges   == thePArray->num_edges   &&
146           aCurPArray->num_vertexs == thePArray->num_vertexs &&
147           aCurPArray->type        == thePArray->type)
148       {
149         (prevnode ? prevnode->next : myFirst) = node->next;
150         if (!myFirst) myLast = NULL;
151         OpenGl_Element::Destroy (theGlCtx, node->elem);
152         delete node;
153         break;
154       }
155     }
156     prevnode = node;
157     node = node->next;
158   }
159 }
160
161 /*----------------------------------------------------------------------*/
162
163 void OpenGl_Group::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
164 {
165   // Is rendering in ADD or IMMEDIATE mode?
166   const Standard_Boolean isImmediate = (AWorkspace->NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE)) != 0;
167
168   // Setup aspects
169   const OpenGl_AspectLine *aspect_line = AWorkspace->AspectLine(Standard_False);
170   const OpenGl_AspectFace *aspect_face = AWorkspace->AspectFace(Standard_False);
171   const OpenGl_AspectMarker *aspect_marker = AWorkspace->AspectMarker(Standard_False);
172   const OpenGl_AspectText *aspect_text = AWorkspace->AspectText(Standard_False);
173   if (myAspectLine)
174     AWorkspace->SetAspectLine(myAspectLine);
175   if (myAspectFace)
176     AWorkspace->SetAspectFace(myAspectFace);
177   if (myAspectMarker)
178     AWorkspace->SetAspectMarker(myAspectMarker);
179   if (myAspectText)
180     AWorkspace->SetAspectText(myAspectText);
181
182   // Render group elements
183   OpenGl_ElementNode *node = myFirst;
184   while (node)
185   {
186     switch (node->type)
187     {
188       case TelPolyline:
189       case TelMarker:
190       case TelMarkerSet:
191       case TelText:
192       {
193         glDisable(GL_LIGHTING);
194
195         if (isImmediate)
196         {
197           glDepthMask(GL_FALSE);
198         }
199         else if ( (AWorkspace->NamedStatus & OPENGL_NS_ANIMATION) != 0 &&
200                   (AWorkspace->NamedStatus & OPENGL_NS_WIREFRAME) == 0 &&
201                    AWorkspace->DegenerateModel != 0 )
202         {
203           glDisable( GL_DEPTH_TEST );
204           if ( AWorkspace->NamedStatus & OPENGL_NS_TEXTURE ) DisableTexture();
205           AWorkspace->NamedStatus |= OPENGL_NS_WIREFRAME;
206         }
207
208         node->elem->Render( AWorkspace );
209
210         if ( !isImmediate && (AWorkspace->NamedStatus & OPENGL_NS_TEXTURE) != 0 ) EnableTexture();
211         break;
212       }
213
214       case TelPolygon:
215       case TelPolygonIndices:
216       case TelQuadrangle:
217       case TelTriangleMesh:
218       {
219         if (isImmediate)
220         {
221           glDepthMask(GL_FALSE);
222         }
223         else if ( (AWorkspace->NamedStatus & OPENGL_NS_ANIMATION) != 0 &&
224                   (AWorkspace->NamedStatus & OPENGL_NS_WIREFRAME) != 0 &&
225                   AWorkspace->DegenerateModel < 2 )
226         {
227           if ( AWorkspace->NamedStatus & OPENGL_NS_TEXTURE ) EnableTexture ();
228
229           glEnable( GL_DEPTH_TEST );
230           AWorkspace->NamedStatus &= ~OPENGL_NS_WIREFRAME;
231         }
232
233         if ( AWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT )
234           AWorkspace->DisablePolygonOffset();
235
236         node->elem->Render( AWorkspace );
237
238         if ( AWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT )
239           AWorkspace->EnablePolygonOffset();
240         break;
241       }
242
243       default:
244       {
245         node->elem->Render( AWorkspace );
246         break;
247       }
248     }
249     node = node->next;
250   }
251
252   // Restore aspects
253   AWorkspace->SetAspectLine(aspect_line);
254   AWorkspace->SetAspectFace(aspect_face);
255   AWorkspace->SetAspectMarker(aspect_marker);
256   AWorkspace->SetAspectText(aspect_text);
257 }
258
259 void OpenGl_Group::Release (const Handle(OpenGl_Context)& theGlCtx)
260 {
261   // Delete elements
262   while (myFirst != NULL)
263   {
264     OpenGl_ElementNode* aNext = myFirst->next;
265     OpenGl_Element::Destroy (theGlCtx, myFirst->elem);
266     delete myFirst;
267     myFirst = aNext;
268   }
269   myLast = NULL;
270
271   OpenGl_Element::Destroy (theGlCtx, myAspectLine);
272   OpenGl_Element::Destroy (theGlCtx, myAspectFace);
273   OpenGl_Element::Destroy (theGlCtx, myAspectMarker);
274   OpenGl_Element::Destroy (theGlCtx, myAspectText);
275 }