0025133: TKOpenGl - Crash on closing a view containing presentations with capping
[occt.git] / src / OpenGl / OpenGl_Group.cxx
1 // Created on: 2011-08-01
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <OpenGl_Group.hxx>
17
18 #include <OpenGl_GraphicDriver.hxx>
19 #include <OpenGl_Flipper.hxx>
20 #include <OpenGl_PrimitiveArray.hxx>
21 #include <OpenGl_StencilTest.hxx>
22 #include <OpenGl_Structure.hxx>
23 #include <OpenGl_Text.hxx>
24 #include <OpenGl_Workspace.hxx>
25
26 #include <Graphic3d_ArrayOfPrimitives.hxx>
27 #include <Graphic3d_CUserDraw.hxx>
28 #include <Graphic3d_GroupDefinitionError.hxx>
29
30 IMPLEMENT_STANDARD_HANDLE (OpenGl_Group, Graphic3d_Group)
31 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Group, Graphic3d_Group)
32
33 // =======================================================================
34 // function : OpenGl_Group
35 // purpose  :
36 // =======================================================================
37 OpenGl_Group::OpenGl_Group (const Handle(Graphic3d_Structure)& theStruct)
38 : Graphic3d_Group (theStruct),
39   myAspectLine(NULL),
40   myAspectFace(NULL),
41   myAspectMarker(NULL),
42   myAspectText(NULL),
43   myFirst(NULL),
44   myLast(NULL),
45   myIsRaytracable (Standard_False),
46   myModificationState (0)
47 {
48   Handle(OpenGl_Structure) aStruct = Handle(OpenGl_Structure)::DownCast (myStructure->CStructure());
49   if (aStruct == NULL)
50   {
51     Graphic3d_GroupDefinitionError::Raise ("OpenGl_Group should be created by OpenGl_Structure!");
52   }
53 }
54
55 // =======================================================================
56 // function : ~OpenGl_Group
57 // purpose  :
58 // =======================================================================
59 OpenGl_Group::~OpenGl_Group()
60 {
61   Release (Handle(OpenGl_Context)());
62 }
63
64 // =======================================================================
65 // function : UpdateAspectLine
66 // purpose  :
67 // =======================================================================
68 void OpenGl_Group::UpdateAspectLine (const Standard_Boolean theIsGlobal)
69 {
70   if (!ContextLine.IsDef)
71   {
72     return;
73   }
74
75   if (theIsGlobal || myFirst == NULL)
76   {
77     if (myAspectLine == NULL)
78     {
79       myAspectLine = new OpenGl_AspectLine();
80     }
81     myAspectLine->SetAspect (ContextLine);
82   }
83   else
84   {
85     OpenGl_AspectLine* anAspectLine = new OpenGl_AspectLine();
86     anAspectLine->SetAspect (ContextLine);
87     AddElement (anAspectLine);
88   }
89 }
90
91 // =======================================================================
92 // function : UpdateAspectFace
93 // purpose  :
94 // =======================================================================
95 void OpenGl_Group::UpdateAspectFace (const Standard_Boolean theIsGlobal)
96 {
97   if (!ContextFillArea.IsDef)
98   {
99     return;
100   }
101
102   if (theIsGlobal || myFirst == NULL)
103   {
104     if (myAspectFace == NULL)
105     {
106       myAspectFace = new OpenGl_AspectFace();
107     }
108     myAspectFace->SetAspect (ContextFillArea);
109   }
110   else
111   {
112     OpenGl_AspectFace* anAspectFace = new OpenGl_AspectFace();
113     anAspectFace->SetAspect (ContextFillArea);
114     AddElement (anAspectFace);
115   }
116
117   if (myIsRaytracable)
118   {
119     ++myModificationState;
120     OpenGl_Structure* aStruct = GlStruct();
121     if (aStruct != NULL)
122     {
123       aStruct->UpdateStateWithAncestorStructures();
124     }
125   }
126 }
127
128 // =======================================================================
129 // function : UpdateAspectMarker
130 // purpose  :
131 // =======================================================================
132 void OpenGl_Group::UpdateAspectMarker (const Standard_Boolean theIsGlobal)
133 {
134   if (!ContextMarker.IsDef)
135   {
136     return;
137   }
138
139   if (theIsGlobal || myFirst == NULL)
140   {
141     if (myAspectMarker == NULL)
142     {
143       myAspectMarker = new OpenGl_AspectMarker();
144     }
145     myAspectMarker->SetAspect (ContextMarker);
146   }
147   else
148   {
149     OpenGl_AspectMarker* anAspectMarker = new OpenGl_AspectMarker();
150     anAspectMarker->SetAspect (ContextMarker);
151     AddElement (anAspectMarker);
152   }
153 }
154
155 // =======================================================================
156 // function : UpdateAspectText
157 // purpose  :
158 // =======================================================================
159 void OpenGl_Group::UpdateAspectText (const Standard_Boolean theIsGlobal)
160 {
161   if (!ContextText.IsDef)
162   {
163     return;
164   }
165
166   if (theIsGlobal || myFirst == NULL)
167   {
168     if (myAspectText == NULL)
169     {
170       myAspectText = new OpenGl_AspectText();
171     }
172     myAspectText->SetAspect (ContextText);
173   }
174   else
175   {
176     OpenGl_AspectText* anAspectText = new OpenGl_AspectText();
177     anAspectText->SetAspect (ContextText);
178     AddElement (anAspectText);
179   }
180 }
181
182 // =======================================================================
183 // function : AddPrimitiveArray
184 // purpose  :
185 // =======================================================================
186 void OpenGl_Group::AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray theType,
187                                       const Handle(Graphic3d_IndexBuffer)& theIndices,
188                                       const Handle(Graphic3d_Buffer)&      theAttribs,
189                                       const Handle(Graphic3d_BoundBuffer)& theBounds,
190                                       const Standard_Boolean               theToEvalMinMax)
191 {
192   if (IsDeleted()
193    || theAttribs.IsNull())
194   {
195     return;
196   }
197
198   OpenGl_Structure* aStruct = GlStruct();
199   const OpenGl_GraphicDriver* aDriver = aStruct->GlDriver();
200
201   OpenGl_PrimitiveArray* anArray = new OpenGl_PrimitiveArray (aDriver, theType, theIndices, theAttribs, theBounds);
202   AddElement (anArray);
203
204   Graphic3d_Group::AddPrimitiveArray (theType, theIndices, theAttribs, theBounds, theToEvalMinMax);
205 }
206
207 // =======================================================================
208 // function : Text
209 // purpose  :
210 // =======================================================================
211 void OpenGl_Group::Text (const Standard_CString                  theTextUtf,
212                          const Graphic3d_Vertex&                 thePoint,
213                          const Standard_Real                     theHeight,
214                          const Quantity_PlaneAngle               theAngle,
215                          const Graphic3d_TextPath                theTp,
216                          const Graphic3d_HorizontalTextAlignment theHta,
217                          const Graphic3d_VerticalTextAlignment   theVta,
218                          const Standard_Boolean                  theToEvalMinMax)
219 {
220   if (IsDeleted())
221   {
222     return;
223   }
224
225   OpenGl_TextParam  aParams;
226   OpenGl_Structure* aStruct = GlStruct();
227   aParams.Height = int ((theHeight < 2.0) ? aStruct->GlDriver()->DefaultTextHeight() : theHeight);
228   aParams.HAlign = theHta;
229   aParams.VAlign = theVta;
230   const OpenGl_Vec3 aPoint (thePoint.X(), thePoint.Y(), thePoint.Z());
231   OpenGl_Text* aText = new OpenGl_Text (theTextUtf, aPoint, aParams);
232   AddElement (aText);
233   Graphic3d_Group::Text (theTextUtf, thePoint, theHeight, theAngle,
234                          theTp, theHta, theVta, theToEvalMinMax);
235 }
236
237 // =======================================================================
238 // function : UserDraw
239 // purpose  :
240 // =======================================================================
241 void OpenGl_Group::UserDraw (const Standard_Address theObject,
242                              const Standard_Boolean theToEvalMinMax,
243                              const Standard_Boolean theContainsFacet)
244 {
245   if (IsDeleted())
246   {
247     return;
248   }
249
250   OpenGl_Structure* aStruct = GlStruct();
251   if (aStruct->GlDriver()->UserDrawCallback() == NULL)
252   {
253     return;
254   }
255
256   Graphic3d_CUserDraw aUserDraw;
257   aUserDraw.Data   = theObject;
258   aUserDraw.Bounds = theToEvalMinMax ? &myBounds : NULL;
259   OpenGl_Element* aUserDrawElem = aStruct->GlDriver()->UserDrawCallback()(&aUserDraw);
260   if (aUserDrawElem != NULL)
261   {
262     AddElement (aUserDrawElem);
263   }
264   Graphic3d_Group::UserDraw (theObject, theToEvalMinMax, theContainsFacet);
265 }
266
267 // =======================================================================
268 // function : SetFlippingOptions
269 // purpose  :
270 // =======================================================================
271 void OpenGl_Group::SetFlippingOptions (const Standard_Boolean theIsEnabled,
272                                        const gp_Ax2&          theRefPlane)
273 {
274   OpenGl_Flipper* aFlipper = new OpenGl_Flipper (theRefPlane);
275   aFlipper->SetOptions (theIsEnabled);
276   AddElement (aFlipper);
277 }
278
279 // =======================================================================
280 // function : SetStencilTestOptions
281 // purpose  :
282 // =======================================================================
283 void OpenGl_Group::SetStencilTestOptions (const Standard_Boolean theIsEnabled)
284 {
285   OpenGl_StencilTest* aStencilTest = new OpenGl_StencilTest();
286   aStencilTest->SetOptions (theIsEnabled);
287   AddElement (aStencilTest);
288 }
289
290 // =======================================================================
291 // function : AddElement
292 // purpose  :
293 // =======================================================================
294 void OpenGl_Group::AddElement (OpenGl_Element* theElem)
295 {
296   OpenGl_ElementNode *aNode = new OpenGl_ElementNode();
297
298   aNode->elem = theElem;
299   aNode->next = NULL;
300   (myLast? myLast->next : myFirst) = aNode;
301   myLast = aNode;
302
303   if (OpenGl_Raytrace::IsRaytracedElement (aNode))
304   {
305     myModificationState++;
306     myIsRaytracable = Standard_True;
307
308     OpenGl_Structure* aStruct = GlStruct();
309     if (aStruct != NULL)
310     {
311       aStruct->UpdateStateWithAncestorStructures();
312       aStruct->SetRaytracableWithAncestorStructures();
313     }
314   }
315 }
316
317 // =======================================================================
318 // function : Render
319 // purpose  :
320 // =======================================================================
321 void OpenGl_Group::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
322 {
323   // Is rendering in ADD or IMMEDIATE mode?
324   const Handle(OpenGl_RenderFilter)& aFilter = theWorkspace->GetRenderFilter();
325
326   // Setup aspects
327   const OpenGl_AspectLine*   aBackAspectLine   = theWorkspace->AspectLine   (Standard_False);
328   const OpenGl_AspectFace*   aBackAspectFace   = theWorkspace->AspectFace   (Standard_False);
329   const OpenGl_AspectMarker* aBackAspectMarker = theWorkspace->AspectMarker (Standard_False);
330   const OpenGl_AspectText*   aBackAspectText   = theWorkspace->AspectText   (Standard_False);
331   Standard_Boolean isLineSet   = myAspectLine   && myAspectLine->RenderFiltered (theWorkspace, aFilter);
332   Standard_Boolean isFaceSet   = myAspectFace   && myAspectFace->RenderFiltered (theWorkspace, aFilter);
333   Standard_Boolean isMarkerSet = myAspectMarker && myAspectMarker->RenderFiltered (theWorkspace, aFilter);
334   Standard_Boolean isTextSet   = myAspectText   && myAspectText->RenderFiltered (theWorkspace, aFilter);
335
336   // Render group elements
337   for (OpenGl_ElementNode* aNodeIter = myFirst; aNodeIter != NULL; aNodeIter = aNodeIter->next)
338   {
339     aNodeIter->elem->RenderFiltered (theWorkspace, aFilter);
340   }
341
342   // Restore aspects
343   if (isLineSet)
344     theWorkspace->SetAspectLine (aBackAspectLine);
345   if (isFaceSet)
346     theWorkspace->SetAspectFace (aBackAspectFace);
347   if (isMarkerSet)
348     theWorkspace->SetAspectMarker (aBackAspectMarker);
349   if (isTextSet)
350     theWorkspace->SetAspectText (aBackAspectText);
351 }
352
353 // =======================================================================
354 // function : Clear
355 // purpose  :
356 // =======================================================================
357 void OpenGl_Group::Clear (const Standard_Boolean theToUpdateStructureMgr)
358 {
359   if (IsDeleted())
360   {
361     return;
362   }
363
364   OpenGl_Structure* aStruct = GlStruct();
365   const Handle(OpenGl_Context)& aCtx = aStruct->GlDriver()->GetSharedContext();
366
367   Release (aCtx);
368   Graphic3d_Group::Clear (theToUpdateStructureMgr);
369 }
370
371 // =======================================================================
372 // function : Release
373 // purpose  :
374 // =======================================================================
375 void OpenGl_Group::Release (const Handle(OpenGl_Context)& theGlCtx)
376 {
377   // Delete elements
378   while (myFirst != NULL)
379   {
380     OpenGl_ElementNode* aNext = myFirst->next;
381     OpenGl_Element::Destroy (theGlCtx.operator->(), myFirst->elem);
382     delete myFirst;
383     myFirst = aNext;
384   }
385   myLast = NULL;
386
387   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectLine);
388   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectFace);
389   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectMarker);
390   OpenGl_Element::Destroy (theGlCtx.operator->(), myAspectText);
391 }